【问题标题】:Calling C++ dll from python从 python 调用 C++ dll
【发布时间】:2020-02-07 02:08:02
【问题描述】:

我在 c++ 中创建了一个 dll 库并将其导出为 c 类型的 dll。库头是这样的: 图书馆.h

struct Surface
{
    char surfReq[10];
};

struct GeneralData
{
    Surface surface;
    char weight[10];
};

struct Output
{
    GeneralData generalData;
    char message[10];
};
extern "C" __declspec(dllexport) int __cdecl Calculation(Output &output);

library.cpp

int Calculation(Output &output)
{
  strcpy_s(output.message, 10, "message");
  strcpy_s(output.generalData.weight, 10, "weight");
  strcpy_s(output.generalData.surface.surfReq, 10, "surfReq");
  return 0;
}

现在我有了这个 Python 脚本:

#! python3-32
from ctypes import *
import sys, os.path

class StructSurface(Structure):
    _fields_ = [("surfReq", c_char_p)]

class StructGeneralData(Structure):
    _fields_ = [("surface", StructSurface),
                ("weight", c_char_p)]

class OutData(Structure):
    _fields_ = [("generalData", StructGeneralData),
                ("message", c_char_p)]

my_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(my_path, "../../../libs/Python.dll")

testDll = cdll.LoadLibrary(path)

surfReq = (b''*10)
structSurface = StructSurface(surfReq)

weight = (b''*10)
structGeneralData = StructGeneralData(structSurface, weight)

message = (b''*10)
outData = OutData(structGeneralData, message) 

testDll.restyp = c_int
testDll.argtypes = [byref(outData)]
testDll.Calculation(outData)
print(outData.message)
print(outData.generalData.weight)
print(outData.generalData.surface.surfReq)

当我从 outData 打印字段时,我在所有字段中得到相同的结果:

b'surfReq'

b'surfReq'

b'surfReq'

您能否告诉我如何指定字符数组/字段,以便我得到正确的结果。我只被允许更改 python 脚本。 我从 C# 调用这个库没有问题。

【问题讨论】:

  • 在问题中将输出作为格式正确的文本包括在内,而不是作为外部链接或图像。
  • Python 代码中的“testDll.Skuska”是什么?一个错误是 C++ 结构包含固定长度的 char 数组,而相应的 ctypes 结构却有 char 指针。
  • 我将testDll.Skuska 更改为testDll.Calculation(错字)。
  • 我尝试了不同的 ctypes。当我尝试c_char * 10(初始化相同)时,我收到一个错误:“python.exe 中 0x78AFEE3F (ucrtbased.dll) 抛出异常:0xC0000005:访问冲突写入位置 0x00000014。” 我有还尝试了c_byte * 10(没有初始化)并得到了相同的访问冲突。此外,当我进入 library.cpp 时,它说通过引用传递的输出参数是 <struct at NULL>
  • “byref”应该只在调用中使用,而不是作为类型(有趣的是 ctypes 接受这个)。因此 argtypes 应该是 [POINTER(OutData)] 并且 Calculation 的实际调用参数应该是 byref(outData)。

标签: python c++ struct dll char


【解决方案1】:

将 python ctypes 更改为 c_char * 10:

class StructSurface(Structure):
    _fields_ = [("surfReq", c_char * 10)]

class StructGeneralData(Structure):
    _fields_ = [("surface", StructSurface),
                ("weight", c_char * 10)]

class OutData(Structure):
    _fields_ = [("generalData", StructGeneralData),
                ("message", c_char * 10)]

并将 argtypes 和实际调用更改为

testDll.argtypes = [POINTER(OutData)]
testDll.Calculation(byref(outData))

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多