Установить значение внешней переменной C ++ из Cython - PullRequest
0 голосов
/ 03 августа 2020

В моем проекте я обертываю код C ++ (который у меня полностью контролируется) с помощью Cython, чтобы иметь возможность вызывать функции C ++ из Python.

В одном из файлов заголовков C ++, которые я хочу использовать ключевое слово extern для определения (но не инициализации) переменной, которая затем используется в соответствующем файле реализации cpp. Я хочу установить значение для этой переменной из оболочки Cython.

Ниже вы можете найти минимальную версию моего кода.

Изменить: как указано @ ead, мой исходный образец кода не подходил для воспроизведения проблемы. Вот минимальный рабочий пример, который лучше подходит для выявления проблемы.

test.h

extern int testVariable;

void function1();

void function2();

test. 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";
}

wrapper1.pyx

cdef extern from "test.h":

    int testVariable

    void function1()


testVariable = 42

cpdef wrapper_function1():
    function1()

wrapper2.pyx

cdef extern from "test.h":

    void function2()


cpdef wrapper_function2():
    function2()

main.py

from wrapper1 import wrapper_function1
from wrapper2 import wrapper_function2

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

setup.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 ++ проблема сохраняется, т.е. testVariable равно 0.

Спасибо за ответы!

PS: Мой код был вдохновлен { ссылка }

1 Ответ

0 голосов
/ 03 августа 2020

Я бы решил эту проблему с помощью класса, например:

header

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;
}

pxd:

cdef extern from "MyCppClass.h":

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

pyx:

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())

, и это отлично работает

...