始终(正确) 为 C中 定义的函数指定 argtypes 和 restype __,否则( C89 风格)它们将 默认为
int (通常为 32bit ),生成 _ ! 未定义的行为!!!。在 _64位上 ,地址(大于 _ 2 GiB_
)将被截断(这正是您所遇到的)。检查[SO]:从Python通过ctypes调用的C函数返回错误值(@CristiFati的答案)以获取更多详细信息。
另外,遇到问题时,请不要忘记[Python 3.Docs]:ctypes-
Python的外部函数库。
下面是代码的改编版本。
detector.cpp :
#include <stdio.h>#include <memory.h>#include <fstream>#define C_TAG "From C"#define PRINT_MSG_2SP(ARG0, ARG1) printf("%s - [%s] (%d) - [%s]: %s: 0x%0pn", C_TAG, __FILE__, __LINE__, __FUNCTION__, ARG0, ARG1)using std::endl;std::ofstream outFile;class Detector { public: Detector(); void process(int *pIn, int *pOut, int n); private: int m_var;};Detector::Detector() : m_var(0) { outFile.open("addr_debug.txt"); outFile << "m_var init address: " << &m_var << endl; PRINT_MSG_2SP("&m_var", &m_var);}void Detector::process(int *pIn, int *pOut, int n) { outFile << "m_var process address: " << &m_var << endl; outFile.close(); PRINT_MSG_2SP("&m_var", &m_var);}#define SIM_EXPORT __declspec(dllexport)#if defined(__cplusplus)extern "C" {#endif SIM_EXPORT Detector *DetectorNew() { return new Detector(); } SIM_EXPORT void DetectorProcess(Detector *pDet, int *pIn, int *pOut, int n) { pDet->process(pIn, pOut, n); } SIM_EXPORT void DetectorDelete(Detector *pDet) { delete pDet; }#if defined(__cplusplus)}#endifpre.py :
import sysfrom ctypes import CDLL, POINTER, c_int, c_void_pimport numpy as npsim_dll = CDLL("./sim.dll")detector_new_func = sim_dll.DetectorNewdetector_new_func.restype = c_void_pdetector_process_func = sim_dll.DetectorProcessdetector_process_func.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int), c_int]detector_delete_func = sim_dll.DetectorDeletedetector_delete_func.argtypes = [c_void_p]class Detector(): def __init__(self): self.obj = detector_new_func() def process(self, pin, pout, n): detector_process_func(self.obj, pin, pout, n) def __del__(self): detector_delete_func(self.obj)def main(): detector = Detector() n = 1024 a = np.arange(n, dtype=np.uint32) b = np.zeros(n, dtype=np.int32) aptr = a.ctypes.data_as(POINTER(c_int)) bptr = b.ctypes.data_as(POINTER(c_int)) detector.process(aptr, bptr, n)if __name__ == "__main__": print("Python {:s} on {:s}n".format(sys.version, sys.platform)) main()注意事项 :
- 正如我在开始时所说,问题是未指定 argtypes 和 restype (例如,对于 DetectorNew :comment
detector_new_func.restype = c_void_p
,您将再次遇到问题) - 问题中的代码缺少部分( #include , import ,…),还存在一些语法错误,因此它无法编译,因此不遵循[SO]:如何创建最小化,完整且可验证的示例(mcve)准则。请在询问时确保拥有 mcve
- 您分配(
new Detector()
)的对象也必须被释放(否则,它将产生 内存泄漏 ),因此我添加了一个函数( DetectorDelete- 为此),该函数从( Python ) Detector 的析构函数进行调用 - 其他(非关键)更改(标识符重命名,一点重构,打印到 stdout 等)
输出 :
(py35x64_tes1)e:WorkDevStackOverflowq052268294>”c:Installx86MicrosoftVisual Studio
Community2015vcvcvarsall.bat” x64(py35x64_test) e:WorkDevStackOverflowq052268294>dir /bpre.pydetector.cpp(py35x64_test) e:WorkDevStackOverflowq052268294>cl /nologo /DDLL/EHsc detector.cpp /link /DLL /OUT:sim.dll
detector.cpp
Creating library sim.lib and object sim.exp(py35x64_test) e:WorkDevStackOverflowq052268294>dir /bpre.pydetector.cppdetector.objsim.dllsim.expsim.lib(py35x64_test)e:WorkDevStackOverflowq052268294>”e:WorkDevVEnvspy35x64_testscriptspython.exe”
./pre.py
Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit
(AMD64)] on win32From C - [detector.cpp] (28) - [Detector::Detector]: &m_var:0x0000020CE366E270
From C - [detector.cpp] (34) - [Detector::process]: &m_var:
0x0000020CE366E270



