我遇到了一个问题,这个dll文件可以被java或php成功调用,但是当我使用python调用时出现访问冲突错误。
我想知道是否c++ char*映射到ctypes c_char_p中有误,以及如何使用python ctypes映射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环境是anaconda,我和我的同学使用相同的环境和代码,但仍然返回相同的错误。
Python vs Java
虽然我知道应该是环境引起的问题,但我真的想知道到底是什么导致了这个问题?
Python
每次运行handle时都会得到不规则的数字,而我的同学的电脑得到的是规则的数字。
例如:288584672、199521248、1777824736、-607161376(我没有设置restype)
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;
}
c_void_p
,正如我已经解释过的那样,您还应该修复DLL的代码。 - benjarobinu_int64
类型。正如我已经解释过的那样,即使C函数原型是整数,您也应该使用c_void_p
。 - benjarobin