【发布时间】:2018-05-06 06:40:43
【问题描述】:
我遇到一个问题,这个dll java或者php可以调用成功,但是当我使用python调用时出现访问冲突错误,
我想知道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 ,它也无法连接。
很高兴我的同学用她的电脑(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,换了和她一样的环境,用一样的代码,还是一样的报错
python 与 java
虽然我知道应该是环境原因,但我很想知道到底是什么原因造成的?
蟒蛇
每次运行手柄都是不规则号,我同学的电脑是固定号
如:288584672,199521248,1777824736,-607161376(我没有设置restype)
this is using python call dll,cann't connect port 4000
java
也可以得到没有负数的常规数
如:9462886128,9454193200,9458325520,9451683632
所以我认为应该是这个代码导致错误,但在其他电脑上没有问题,这很神奇
handle = lib.Initialization(5, '127.0.0.1'.encode(), 4000)
c++ dll:
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;
}
【问题讨论】:
-
Java 正在返回 64 位值(注意返回数字有多大)。在 python 中,如果您不指定 restype,则默认为
int,这是一个有符号整数,这就是您看到负数的原因。在python中你必须使用c_void_p,正如我已经解释过的,你还应该修复DLL的代码 -
据我所知,在 Python ctypes
u_int64类型中不存在。正如我已经解释过的,即使 C 函数原型是整数,你也应该使用c_void_p -
你同学的代码是错误的,她只是幸运的是指针适合32位整数
-
想你,我会尽快修改的