Всегда (ПРАВИЛЬНО) указывайте argtypes и restype для функций, определенных в C , в противном случае ( C89 стиль) они будут по умолчанию int (обычно 32bit ), генерируя !!!Неопределенное поведение !!! .На 64 бит адреса (больше чем 2 ГиБ ) будут усечены (это именно то, что вы испытываете).
Еще одно последствие той же ошибки: [SO]: проблема с типами Python в разных ОС (ответ @ CristiFati) .
Кроме того, при возникновении проблем не забывайте о [Python 3.Docs]: ctypes - библиотека сторонних функций для Python .
Ниже приведена адаптированная версия вашего кода.
dete.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%0p\n", 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)
}
#endif
code.py :
import sys
from ctypes import CDLL, POINTER, \
c_int, c_void_p
import numpy as np
sim_dll = CDLL("./sim.dll")
detector_new_func = sim_dll.DetectorNew
detector_new_func.restype = c_void_p
detector_process_func = sim_dll.DetectorProcess
detector_process_func.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int), c_int]
detector_delete_func = sim_dll.DetectorDelete
detector_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 : комментарий
detector_new_func.restype = c_void_p
, и вы столкнетесь с проблемойснова) - В указанном коде отсутствуют части ( # включают s, import s, ...), также есть некоторые синтаксические ошибки, поэтому он нене компилируется и поэтому не следует [SO]: Как создать руководство по минимальному, полному и проверяемому примеру (mcve) .Пожалуйста, убедитесь, что у вас есть mcve при запросе
- Объект, который вы выделяете (
new Detector()
), также должен быть освобожден (в противном случае это вызовет утечка памяти ), поэтому я добавил функцию ( DetectorDelete - для этого), которая вызывается из ( Python ) Detector деструктор - Другие (некритические) изменения (переименование идентификаторов, небольшой рефакторинг, печать в stdout , ...)
Вывод :
(py35x64_tes1) e:\Work\Dev\StackOverflow\q052268294>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x64
(py35x64_test) e:\Work\Dev\StackOverflow\q052268294>dir /b
code.py
detector.cpp
(py35x64_test) e:\Work\Dev\StackOverflow\q052268294>cl /nologo /DDLL /EHsc detector.cpp /link /DLL /OUT:sim.dll
detector.cpp
Creating library sim.lib and object sim.exp
(py35x64_test) e:\Work\Dev\StackOverflow\q052268294>dir /b
code.py
detector.cpp
detector.obj
sim.dll
sim.exp
sim.lib
(py35x64_test) e:\Work\Dev\StackOverflow\q052268294>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" ./code.py
Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
From C - [detector.cpp] (28) - [Detector::Detector]: &m_var: 0x0000020CE366E270
From C - [detector.cpp] (34) - [Detector::process]: &m_var: 0x0000020CE366E270