[英]call c++ function from python
我遇到一个问题,这个dll java或者php可以调用成功,但是当我使用python调用get access violation错误时,
我想知道c ++ char *是ctypes c_char_p的错误,我怎么能用python ctypes map c ++ char *
c ++ dll定义
#define Health_API extern "C" __declspec(dllexport)
Health_API unsigned long Initialization(int m_type,char * m_ip,int m_port)
Health_API int GetRecordCount(unsigned long m_handle)
python代码
from ctypes import *
lib = cdll.LoadLibrary(r"./Health.dll")
inita = lib.Initialization
inita.argtype = (c_int, c_char_p, c_int)
inita.restype = c_ulong
getcount = lib.GetRecordCount
getcount.argtype = c_ulong
getcount.retype = c_int
# here call
handle = inita(5, '127.0.0.1'.encode(), 4000)
print(handle)
result = getcount(handle)
错误信息:
2675930080
Traceback (most recent call last):
File "C:/Users/JayTam/PycharmProjects/DecoratorDemo/demo.py", line 14, in <module>
print(getcount(handle))
OSError: exception: access violation reading 0x000000009F7F73E0
我发现如果没有定义restype = long,它会返回负数,这是一个值得注意的问题,但我更改了restype = u_int64,它也无法连接。
令我高兴的是,我的shcoolmate使用她的电脑(win7 x64)调用相同的dll成功,使用简单的代码如下
from ctypes import *
lib = cdll.LoadLibrary("./Health.dll")
handle = lib.Initialization(5, '127.0.0.1'.encode(), 4000)
lib.GetRecordList(handle, '')
我是win10 x64,我的python环境是annaconda,我和她改变了相同的环境,使用相同的代码,仍然返回相同的错误
虽然我知道它应该是环境原因,但我真的想知道究竟是什么导致了它?
每个运行句柄都是不规则号码,我同学的pc得到常规号码
如:288584672,199521248,1777824736,-607161376(我不设置restype)
也可以获得没有负数的常规数字
如:9462886128,9454193200,9458325520,9451683632
所以我认为应该是这个代码casue错误,但在其他PC没有问题,这是惊人的
handle = lib.Initialization(5, '127.0.0.1'.encode(), 4000)
Health_API unsigned long Initialization(int m_type,char* m_ip,int m_port)
{
CHandleNode* node;
switch(m_type)
{
case BASEINFO:
{
CBaseInfo* baseInfo = new CBaseInfo;
baseInfo->InitModule(m_ip,m_port);
node = m_info.AddMCUNode((unsigned long)baseInfo);
node->SetType(m_type);
return (unsigned long)baseInfo;
}
break;
case BASEINFO_ALLERGENS:
{
CBaseInfo_Allergens* baseInfo_Allergens = new CBaseInfo_Allergens;
baseInfo_Allergens->InitModule(m_ip,m_port);
node = m_info.AddMCUNode((unsigned long)baseInfo_Allergens);
node->SetType(m_type);
return (unsigned long)baseInfo_Allergens;
}
break;
. (case too many, ... represent them)
.
.
}
return -1;
}
Health_API int GetRecordList(unsigned long m_handle,char* m_index)
{
CHandleNode* node = m_info.GetMCUNode(m_handle);
if( node == NULL)
{
return -1;
}
switch(node->GetType())
{
case BASEINFO:
{
CBaseInfo* baseInfo = (CBaseInfo*)m_handle;
return baseInfo->GetRecordList(m_index);
}
break;
case BASEINFO_ALLERGENS:
{
CBaseInfo_Allergens* baseInfo_Allergens = (CBaseInfo_Allergens *)m_handle;
return baseInfo_Allergens->GetRecordList(m_index);
}
break;
. (case too many, ... represent them)
.
.
}
return -1;
}
拥有C ++的源代码可能会有所帮助,但我可以做一些猜测
我不认为这是相关的,但是:
getcount.retype
缺少s
,应该是restype
。 argtype
定义为数组而不是元组,如果只有一个参数,我仍然使用一个元素的数组。 如果char*
是以空字符结尾的字符串,则确实需要使用c_char_p
。 在这种情况下,强烈建议在m_ip
参数中添加一个const
。
如果char*
是指向原始缓冲区的指针(由调用函数填充或不填充),这不是这里的情况,则需要使用POINTER(c_char)
而不是c_char_p
根据错误消息,您的handle
是一个指针,您应该在C ++代码中使用正确的类型: void*
。 在你的python中你应该使用c_void_p
是64位代码吗? 使用什么工具链/编译器来构建DLL? 这个工具链中unsigned long的大小是多少?
编辑:这里是你的问题的原因: 在64位系统上Python是ctypes.c_long 64位吗?
handle
是DLL中的一个指针,当然是使用long
为64位的编译器构建的,但对于Windows上的python 64位, long
为32位,无法存储指针。 你真的应该使用一个void*
首先,您可以尝试在python中使用c_void_p
来处理句柄,而无需修改源代码,它可能会根据所使用的编译器而有效。 但是由于long
类型的大小没有被任何标准定义,并且可能无法存储指针,所以你真的应该在你的C ++代码中使用void*
或uintptr_t
Edit2:如果你使用的是visual studio,而不是GCC,那么long的大小只有32位( x64平台上的长度与int的大小 )所以你必须修复DLL的代码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.