Tuyệt vời!
Không đầy đủ nhưng đầy đủ. Tôi đã có thể thực hiện thủ thuật cho mục đích của riêng mình. Kết hợp bài đăng này với các nguồn được liên kết ở trên. Nó không phải là dễ dàng, vì tôi là người mới bắt đầu tại Cython, nhưng tôi xác nhận rằng đó là cách duy nhất tôi có thể tìm thấy trên www.
Cảm ơn bạn rất nhiều.
Tôi xin lỗi mà tôi không có quá nhiều thời gian đi sâu vào chi tiết văn bản, nhưng đây là tác phẩm của tôi (có thể giúp đỡ để có được một điểm bổ sung quan điểm về cách đặt tất cả những điều này với nhau)
thiết lập py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [
Extension("elps",
sources=["elps.pyx", "src/ITestClass.cpp"],
libraries=["elp"],
language="c++",
)
]
)
TestClass:
#ifndef TESTCLASS_H_
#define TESTCLASS_H_
namespace elps {
class TestClass {
public:
TestClass(){};
virtual ~TestClass(){};
int getA() { return this->a; };
virtual int override_me() { return 2; };
int calculate(int a) { return a * this->override_me(); }
private:
int a;
};
} /* namespace elps */
#endif /* TESTCLASS_H_ */
ITestClass.h:
#ifndef ITESTCLASS_H_
#define ITESTCLASS_H_
// Created by Cython when providing 'public api' keywords
#include "../elps_api.h"
#include "../../inc/TestClass.h"
namespace elps {
class ITestClass : public TestClass {
public:
PyObject *m_obj;
ITestClass(PyObject *obj);
virtual ~ITestClass();
virtual int override_me();
};
} /* namespace elps */
#endif /* ITESTCLASS_H_ */
ITestClass.cpp:
#include "ITestClass.h"
namespace elps {
ITestClass::ITestClass(PyObject *obj): m_obj(obj) {
// Provided by "elps_api.h"
if (import_elps()) {
} else {
Py_XINCREF(this->m_obj);
}
}
ITestClass::~ITestClass() {
Py_XDECREF(this->m_obj);
}
int ITestClass::override_me()
{
if (this->m_obj) {
int error;
// Call a virtual overload, if it exists
int result = cy_call_func(this->m_obj, (char*)"override_me", &error);
if (error)
// Call parent method
result = TestClass::override_me();
return result;
}
// Throw error ?
return 0;
}
} /* namespace elps */
EDIT2: Một lưu ý về phương pháp ảo PURE (nó dường như là một mối quan tâm khá thường xuyên). Như được hiển thị trong đoạn mã trên, trong thời trang cụ thể đó, "TestClass :: override_me()" KHÔNG THỂ thuần khiết vì nó phải được gọi trong trường hợp phương thức này không được ghi đè trong lớp mở rộng của Python (aka: một không rơi vào phần "lỗi"/"ghi đè không tìm thấy" của nội dung "ITestClass :: override_me()").
Extension: elps.pyx:
cimport cpython.ref as cpy_ref
cdef extern from "src/ITestClass.h" namespace "elps" :
cdef cppclass ITestClass:
ITestClass(cpy_ref.PyObject *obj)
int getA()
int override_me()
int calculate(int a)
cdef class PyTestClass:
cdef ITestClass* thisptr
def __cinit__(self):
##print "in TestClass: allocating thisptr"
self.thisptr = new ITestClass(<cpy_ref.PyObject*>self)
def __dealloc__(self):
if self.thisptr:
##print "in TestClass: deallocating thisptr"
del self.thisptr
def getA(self):
return self.thisptr.getA()
# def override_me(self):
# return self.thisptr.override_me()
cpdef int calculate(self, int a):
return self.thisptr.calculate(a) ;
cdef public api int cy_call_func(object self, char* method, int *error):
try:
func = getattr(self, method);
except AttributeError:
error[0] = 1
else:
error[0] = 0
return func()
Cuối cùng, các cuộc gọi python:
from elps import PyTestClass as TC;
a = TC();
print a.calculate(1);
class B(TC):
# pass
def override_me(self):
return 5
b = B()
print b.calculate(1)
này nên làm công việc liên quan trước hy vọng hơn thẳng vào vấn đề chúng ta đang thảo luận ở đây ..
EDIT: Mặt khác, mã trên có thể được tối ưu hóa bằng cách sử dụng 'hasattr' thay vì khối try/catch:
cdef public api int cy_call_func_int_fast(object self, char* method, bint *error):
if (hasattr(self, method)):
error[0] = 0
return getattr(self, method)();
else:
error[0] = 1
Mã trên, tất nhiên, chỉ tạo sự khác biệt trong trường hợp chúng tôi không ghi đè phương thức 'ghi đè lên'.
Bạn đã thử mã của mình chưa? –
có tất nhiên. Nó trả về 2. Bạn có cần nguồn pyx không (đó là đồng bằng sai nhưng tôi không thể tìm thấy một sửa chữa cho nó chưa)? – ascobol
Không, tôi không nghĩ tôi có thể giúp. Tôi nghĩ rằng boost.python hỗ trợ điều này. –