为什么此ctypes包装函数c_long(0)而不是c_long(3)的返回值?

Why is the return value of this ctypes wrapper function c_long(0) and not c_long(3)?

// main.cpp

#include <iostream>

class AComplicatedCPPObj {

    int *d_;

public:

    explicit AComplicatedCPPObj(int *d)
            : d_(d) {
    }

    int *getD() const {
        return d_;
    }

    void setD(int *d) {
        d_ = d;
    }
};


#ifdef CTYPESTEST_EXPORTS
#if defined(_WIN64)
#define CTYPESTEST_API __declspec(dllexport)
#else
#define CTYPESTEST_API __declspec(dllimport)
#endif

#endif

extern "C" {
CTYPESTEST_API AComplicatedCPPObj *AComplicatedCPPObj_new(int *d) {
    return new AComplicatedCPPObj(d);
}

CTYPESTEST_API int *AComplicatedCPPObj_getD(AComplicatedCPPObj *aComplicatedCppObj) {
    return aComplicatedCppObj->getD();
}

CTYPESTEST_API void AComplicatedCPPObj_setD(AComplicatedCPPObj *aComplicatedCppObj, int *d) {
    aComplicatedCppObj->setD(d);
}

}

cmake脚本编译为共享库

cmake_minimum_required(VERSION 3.15)
project(ctypesTest)

set(CMAKE_CXX_STANDARD 14)

add_library(ctypesTest SHARED main.cpp)
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/INSTALL)
add_definitions("-DCTYPESTEST_EXPORTS=TRUE")
install(TARGETS ctypesTest)

在python端:

import ctypes as ct
import os, glob, sys

WORKING_DIRECTORY = os.path.dirname(__file__)

# find the shared library
if sys.platform == "linux":
    so_path = os.path.join(WORKING_DIRECTORY, "INSTALL/lib/libctypesTest.so")
else:
    so_path = os.path.join(WORKING_DIRECTORY, "INSTALL/bin/ctypesTest.dll")

if not os.path.isfile(so_path):
    raise FileNotFoundError(so_path)

# load sharedd library into python
lib = ct.CDLL(so_path)


class AComplicatedCPPObj:

    def __init__(self, d):
        self.set_function_types("AComplicatedCPPObj_new", [ct.POINTER(ct.c_int)], ct.c_void_p)
        # checking some ctyeps functions
        print("d", d, ct.c_int(d), ct.pointer(ct.c_int(d)), ct.pointer(ct.c_int(d)).contents)

        self.obj = lib.AComplicatedCPPObj_new(ct.pointer(ct.c_int(d)))

        self.set_function_types("AComplicatedCPPObj_getD", [ct.c_void_p], ct.POINTER(ct.c_long))
        self.set_function_types("AComplicatedCPPObj_setD", [ct.c_void_p, ct.POINTER(ct.c_long)], None)

    def set_function_types(self, func_name, argtypes, restype):
        f = lib.__getattr__(func_name)
        f.argtypes = argtypes
        f.restype = restype

    def getD(self):
        return lib.AComplicatedCPPObj_getD(self.obj).contents

    def setD(self, d):
        if isinstance(d, str):
            d = d.encode()

        return lib.AComplicatedCPPObj_setD(self.obj, d)


if __name__ == '__main__':
    o = AComplicatedCPPObj(3)
    print(o.getD())

返回:

d 3 c_long(3) <__main__.LP_c_long object at 0x000001F66F0E8248> c_long(3)
c_long(0)

当我期望看到

d 3 c_long(3) <__main__.LP_c_long object at 0x000001F66F0E8248> c_long(3)
c_long(3)
评论