先贴停止工作的截图
具体的函数定义是这样的
//获取二维码
//参数
//object 接口指针对象
//result 二级指针,返回执行结果 on 字符串,返回执行结果
int WINAPI GetQRCode(void** object, char **result);
我的 python 代码
# 之前的代码就忽略了,wx_user 已经创建好,没有问题。
buffer = create_string_buffer(3000)
result = lib.GetQRCode(wx_user, buffer)
# result = lib.GetQRCode(wx_user, pointer(buffer))
# result = lib.GetQRCode(wx_user, addressof(buffer))
因为传入的第二个参数是要可写的,所以创建了一个可写的缓冲区,希望 dll 将字符串写到这个指针所指向的内存中,之后我再通过 python 读取出来,实现将一个字符串传递出来,而不是通过返回值的方式。
但是我试了好多种办法,包括代码中的三种,还有设置参数和返回值类型的方式都不行,都会在写的时候导致 python 停止运行。
查询了异常代码,可能是在写内存的时候(越界或者其他的错误)导致的问题。
可是这个创建缓冲区的方式是官方文档里找到的,只有这一个函数来创建可以写的内存。
也找了其他语言调用这个这个函数的方式,C# 是直接传入一个整形的值,调试了下看得出来应该是内存地址的整数形式,易语言是传入了一个整形变量的地址,这两种都可以成功调用,我用 python 也模拟了两个方式,都不能成功调用。
所以想问问有没有 ctypes 用的数量的大佬,帮忙看看。万分感谢。
附:dll 只有 api 文档, 没有源码,只能通过文档去调用。
1
zfj1441 2019-11-14 19:49:41 +08:00 via iPhone
换 32 位 python 试试
|
2
no1xsyzy 2019-11-14 19:53:23 +08:00 1
大概:你需要注意 result 的要求是 char** ,而你给了个 char*
我猜测,它应该是自己在堆上写字符串,然后把这个字符串的指针通过一个可写的 char* 弹回给你,而不是往你提供的内存写。 C 语言代码类似这样: char* result=NULL; void* object=...; GetQRCode(&object, &result); |
3
no1xsyzy 2019-11-14 19:53:54 +08:00
|
4
1462326016 OP @zfj1441 抱歉,忘了贴环境了,环境是 win7 64 位旗舰版,python 是 32 位的,因为 dll 也是 32 位的,所以必须要用 32 位的 python 来调用
|
5
Kisesy 2019-11-14 20:07:12 +08:00
一般来说,往外传都要用 byref()
|
6
1462326016 OP @Kisesy 同样也已经试过 byref,各种组合方式都试过了,花了一天多时间试遍了。。。哭。。
|
7
1462326016 OP @no1xsyzy 感谢提示,我参考下
|
8
ysc3839 2019-11-14 20:42:25 +08:00 via Android
这异常代码和“Segmentation fault”一样——都说明不了具体错误是啥。
|
9
no1xsyzy 2019-11-14 21:08:54 +08:00
|
10
1462326016 OP @ysc3839 对的,只是提供给大家做一个参考,因为也没有其他的信息可以提供,只能贴一下截图了
|
11
1462326016 OP @no1xsyzy 因为 dll 不是我写的,文档也是别人提供的,所以我猜想可能 dll 的作者没有按照标准做法来使用传入的参数导致了这个问题,但是因为没有源码所以无从考证,只能多参考下其他人的做法,多尝试下,看能不能找到一些线索。官方文档我也看了好多遍,各种 ctypes 下的函数也都试了好几次,还是同样的报错,目前来说没有什么头绪。
|
12
ysc3839 2019-11-14 21:22:50 +08:00 via Android
@1462326016 发一下你改过的代码来看看?如果可以的话发一下 dll ?
|
13
no1xsyzy 2019-11-14 22:12:08 +08:00
@1462326016 不过 C# 的需要更多信息,尤其是 *result 是否发生变化,从什么变化到什么。
既然传的是 “内存地址的整数形式”,那就肯定应该看 *result 是否变化,作为整型的和作为 char[] 的都要看。 而且确实如果能有一个最小复现环境是最好的。 最后的杀手锏:用 C# 再包一层 |
14
1462326016 OP @no1xsyzy
贴下关键代码。 C#的导入函数定义,传入了两个整形的变量 ``` [DllImport("pad.dll", EntryPoint = "GetQRCode")] public static extern int GetQRCode(int objects, int result); ``` ``` int pushStr; fixed (PushStr = &pushStr) //未执行下边代码时 Marshal.PtrToStringAnsi(new IntPtr(Convert.ToInt32(pushStr)))字符串为 null Dll.GetQRCode(User, (int)PushStr); var msg = Marshal.PtrToStringAnsi(new IntPtr(Convert.ToInt32(pushStr))); //上边这句话 msg 获取到了字符串,所以根据函数定义和上述代码猜测是传入了整形的地址。 ``` pushStr 是 0x028aa1e0 这种形式的 (int)PushStr 传入的参数是 42639840 这种形式的。 两个值在函数调用过程中都没有变过 |
15
1462326016 OP @ysc3839 已发
|