首页 > 解决方案 > 从 Cython 设置 C++ 外部变量的值

问题描述

在我的项目中,我使用 Cython 包装了一些 C++ 代码(我可以完全控制),以便能够从 Python 调用 C++ 功能。

在其中一个 C++ 头文件中,我想使用“extern”关键字来定义(但不初始化)一个变量,然后在相应的 cpp 实现文件中使用该变量。我想从 Cython 包装器中设置该变量的值。

在下面,您可以找到我的代码的最小版本。

编辑:正如@ead 所指出的,我的原始代码示例不适合重现该问题。这是一个更适合指出问题的最小工作示例。

测试.h

extern int testVariable;

void function1();

void function2();

测试.cpp

#include "test.h"
#include <iostream>

int testVariable;

void function1() {
    std::cout << "function1 called, testVariable = " << testVariable << "\n";
}

void function2() {
    std::cout << "function2 called, testVariable = " << testVariable << "\n";
}

包装器1.pyx

cdef extern from "test.h":

    int testVariable

    void function1()


testVariable = 42

cpdef wrapper_function1():
    function1()

包装器2.pyx

cdef extern from "test.h":

    void function2()


cpdef wrapper_function2():
    function2()

主文件

from wrapper1 import wrapper_function1
from wrapper2 import wrapper_function2

if __name__ == '__main__':
    wrapper_function1()
    wrapper_function2()

安装程序.py

from Cython.Build import cythonize
from setuptools import setup, Extension

sources = [
    '*.pyx',
    'test.cpp'
]

extensions = [
    Extension(name='*', sources=sources, language='c++')
]

setup(name='test',
      packages=['test'],
      install_requires=["Cython>=0.29.0"],
      python_requires='>=3.7',
      ext_modules=cythonize(extensions, language_level='3'))

代码是通过命令编译的python3.7 setup.py build_ext --inplace

执行时main.py,输出如下:

function1 called, testVariable = 42
function2 called, testVariable = 0

调用时,function1一切都按预期工作,即testVariable设置为 42。调用function2时,包装在单独的 Cython 文件中,testVariable似乎未初始化,这让我感到惊讶,因为testVariable它应该是一个全局变量。

我将包装器拆分为两个 pyx 文件,因为我实际上不想function2从 Python 调用,而是从 C++ 调用(为简洁起见,此处未显示代码)。从 C++ 调用函数时,问题依然存在,即为testVariable0。

感谢您的回答!

PS:我的代码灵感来自https://stackoverflow.com/a/52925796

标签: c++cythonextern

解决方案


我会使用一个类来解决这个问题,比如:

标题

extern int m_nfoo;


class   __declspec(dllexport)  MyCppClass
{
public:
    MyCppClass();
    ~MyCppClass(void);

    int GetFoo();
    void SetFoo(int Foo);
....

C++:

int m_nFoo=0;


int MyCppClass::GetFoo()
{ 
    return m_nFoo;
}

void MyCppClass::SetFoo(int Foo)
{ 
    m_nFoo=Foo;
}

像素:

cdef extern from "MyCppClass.h":

     
    cdef cppclass MyCppClass:
        MyCppClass()
        int GetFoo()
        void SetFoo(int Foo)

皮克斯:

cdef class myClass:
    """
    wrapper of MyCppClass
    """
       
    def __cinit__(self):
        self.thisptr = new MyCppClass()
        
    def setFoo(self,foo):
        self.thisptr.SetFoo(foo)
        
    def getFoo(self):
        return self.thisptr.GetFoo()   

在一些py中:

    I=myClass()

    I.setFoo(42)
    print ('foo=',I.getFoo())

这很好用


推荐阅读