Компиляция с включенными предупреждениями, и я получаю:
x.cpp(17): warning C4190: 'init_point_by_value' has C-linkage specified, but returns UDT 'Point'
which is incompatible with C
Это из-за объекта, имеющего деструктор.Удалите деструктор, и он должен его принять.
Другая проблема - неправильный тип возврата init_point_by_value
.Это не POINTER(Point)
, а просто Point
:
lib.init_point_by_value.restype = Point
Наконец, не пытайтесь освободить возвращаемый по значению объект.
Результат с исправлениямиследующим образом (немного адаптировано для моей системы Windows):
test.cpp
#include <iostream>
#define API __declspec(dllexport) // Windows-specific export
extern "C" {
using namespace std;
struct Point {
int x;
int y;
};
API Point init_point_by_value(int x, int y) {
cout << "init_point_by_value called" << endl;
Point p;
p.x = x;
p.y = y;
return p;
}
API Point& init_point_by_ref(int x, int y) {
cout << "init_point_by_ref called" << endl;
Point* p = new Point;
p->x = x;
p->y = y;
return *p;
}
API void cleanup_point(Point* point) {
cout << "cleanup_point called" << endl;
if (point) {
delete point;
}
}
}
test.py
import ctypes
class Point(ctypes.Structure):
_fields_ = [
('x', ctypes.c_int),
('y', ctypes.c_int),
]
def setup_lib(lib_path):
lib = ctypes.cdll.LoadLibrary(lib_path)
lib.cleanup_point.argtypes = [ctypes.POINTER(Point)]
lib.init_point_by_value.argtypes = [ctypes.c_int, ctypes.c_int]
lib.init_point_by_value.restype = Point
lib.init_point_by_ref.argtypes = [ctypes.c_int, ctypes.c_int]
lib.init_point_by_ref.restype = ctypes.POINTER(Point)
return lib
lib = setup_lib('test')
p1 = lib.init_point_by_ref(3, 4)
print(p1.contents.x,p1.contents.y)
lib.cleanup_point(p1)
p2 = lib.init_point_by_value(5, 6)
print(p2.x,p2.y)
Выход
init_point_by_ref called
3 4
cleanup_point called
init_point_by_value called
5 6