У меня возникли проблемы с связью C++ (98) с python 3. У меня есть некоторые базовые классы в C++, которые я хотел бы расширить в Python. Некоторые рассматриваемые методы являются чисто виртуальными на стороне C++ и, таким образом, будут реализованы на стороне Python.Наследование базы из C++ в Python, вызов абстрактного метода с использованием SWIG
В настоящее время я могу назвать абстрактные методы из C++ и, по swig, специализация вызывается в Python. Круто. У меня возникли проблемы передав параметры в Python ..
Minimal полного примера, чтобы упростить свою задачу:
// iBase.h
#pragma once
#include <memory>
typedef enum EMyEnumeration{
EMyEnumeration_Zero,
EMyEnumeration_One,
EMyEnumeration_Two
}TEMyEnumeration;
class FooBase{
protected:
int a;
public:
virtual int getA() = 0 ;
};
class Foo : public FooBase{
public:
Foo() {a = 2;}
int getA(){return a;}
};
class iBase{
public:
virtual void start() =0;
virtual void run(std::shared_ptr<FooBase> p, TEMyEnumeration enumCode) = 0;
};
На Swig стороны:
// myif.i
%module(directors="1") DllWrapper
%{
#include <iostream>
#include "iBase.h"
%}
%include <std_shared_ptr.i>
%shared_ptr(FooBase)
%shared_ptr(Foo)
%feature("director") FooBase;
%feature("director") iBase;
%include "iBase.h"
Run: как глоток
swig -c++ -python myif.i
swig -Wall -c++ -python -external-runtime runtime.h
Compile myif_wrap.cxx -> _DllWrapper.pyd
Создайте * .exe со следующим кодом, он загрузит библиотеку _DllWrapper.pyd (убедитесь, что она находится в том же каталоге!). Кроме того, скопируйте файл DllWrapper.py, сгенерированный при помощи swig в каталог exe.
//Main_SmartPtr.cpp
#include "stdafx.h"
#include <Python.h>
#include <windows.h>
#include <string>
#include <memory>
#include "iBase.h"
#include "runtime.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string moduleName = "ExampleSmartPtr";
// load *.pyd (actually a dll file which implements PyInit__<swigWrapperName>)
auto handle =LoadLibrary("_DllWrapper.pyd");
// getting an instance handle..
Py_Initialize();
PyObject *main = PyImport_AddModule("__main__");
PyObject *dict = PyModule_GetDict(main);
PyObject *module = PyImport_Import(PyString_FromString(moduleName.c_str()));
PyModule_AddObject(main, moduleName.c_str(), module);
PyObject *instance = PyRun_String(string(moduleName+string(".")+moduleName+string("()")).c_str(), Py_eval_input, dict, dict);
//calling start() in the Python derived class..
//PyObject *result = PyObject_CallMethod(instance, "start", (char *)"()");
// trying to call run in the Python derived class..
shared_ptr<Foo> foo = make_shared<Foo>();
EMyEnumeration enumCode = EMyEnumeration_Two;
string typeName1 = "std::shared_ptr <FooBase> *";
swig_type_info* info1 = SWIG_TypeQuery(typeName1.c_str());
auto swigData1 = SWIG_NewPointerObj((void*)(&foo), info1, SWIG_POINTER_OWN);
string typeName2 = "TEMyEnumeration *";
swig_type_info* info2 = SWIG_TypeQuery(typeName2.c_str());
auto swigData2 = SWIG_NewPointerObj((void*)(&enumCode), info2, SWIG_POINTER_OWN);
auto result = PyObject_CallMethod(instance, "run", (char *)"(O)(O)", swigData1, swigData2);
return 0;
}
Создать новый файл Python и поместить его в каталог EXE в:
#ExampleSmartPtr.py
import DllWrapper
class ExampleSmartPtr(DllWrapper.iBase):
def __init__(self): # constructor
print("__init__!!")
DllWrapper.iBase.__init__(self)
def start(self):
print("start")
return 0
def run(self, data, enumCode):
print("run")
print("-> data: "+str(data))
print("-> enumCode: "+str(enumCode))
print (data.getA())
return 1
Выходной сигнал запуска ехе является:
__init__!!
run
-> data: (<DllWrapper.FooBase; proxy of <Swig Object of type 'std::shared_ptr<FooBase> *' at 0x00000000014F8B70> >,)
-> enumCode: (<Swig Object of type 'TEMyEnumeration *' at 0x00000000014F89F0>,)
Как можно 'разыменования' enumCode к простому int? Как вы вызываете print (data.getA()) в классе python run()? В его нынешнем виде он ничего не печатает.
Я подозреваю, что ваша проблема заключается в использовании shared_ptr. Работает ли он, когда вместо обычного указателя вы используете обычный тип данных? –
сделайте * минимальный * и полный пример, который мы можем попробовать для себя, что иллюстрирует проблему. Без файлов заголовков (которые предположительно большие) я не могу отлаживать это сам. – Flexo
Где вы определяете EMediaSampleMeta? Я бы ожидал, что% include «emediasamplemeta.h», но вы это забыли? –