Python 和 ctypes:如何正确地将“指针对指针”传递给 DLL?
Posted
技术标签:
【中文标题】Python 和 ctypes:如何正确地将“指针对指针”传递给 DLL?【英文标题】:Python and ctypes: how to correctly pass "pointer-to-pointer" into DLL? 【发布时间】:2011-05-11 21:59:52 【问题描述】:我有一个分配内存并返回它的 DLL。 DLL中的函数是这样的:
void Foo( unsigned char** ppMem, int* pSize )
* pSize = 4;
* ppMem = malloc( * pSize );
for( int i = 0; i < * pSize; i ++ ) (* ppMem)[ i ] = i;
另外,我有一个 python 代码可以从我的 DLL 访问这个函数:
from ctypes import *
Foo = windll.mydll.Foo
Foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
mem = POINTER( c_ubyte )()
size = c_int( 0 )
Foo( byref( mem ), byref( size ) ]
print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]
我希望 print
会显示“4 0 1 2 3”,但它会显示“4 221 221 221 221”O_O。任何提示我做错了什么?
【问题讨论】:
我认为您需要在 Python 端创建一个ppMem
变量,它是一个指向指针的指针,将其初始化为指向您的 mem
变量,然后将其按值传递给 dll 函数.
如果你提出这个建议:pastebin.com/85yBmk92 比它不能得到完全相同的结果:(
【参考方案1】:
发布实际代码。 C/C++ 代码不能编译为 C 或 C++。 Python 代码有语法错误(] 结束函数调用 Foo)。下面的代码有效。修复语法和编译器错误后的主要问题是声明函数 __stdcall
以便 windll
可以在 Python 代码中使用。另一种选择是使用__cdecl
(通常是默认值)并在Python 代码中使用cdll
而不是windll
。
mydll.c (cl /W4 /LD mydll.c)
#include <stdlib.h>
__declspec(dllexport) void __stdcall Foo(unsigned char** ppMem, int* pSize)
char i;
*pSize = 4;
*ppMem = malloc(*pSize);
for(i = 0; i < *pSize; i++)
(*ppMem)[i] = i;
demo.py(Python 2/3 和 32-/64 位兼容)
from __future__ import print_function
from ctypes import *
Foo = WinDLL('./mydll').Foo
Foo.argtypes = POINTER(POINTER(c_ubyte)), POINTER(c_int)
Foo.restype = None
mem = POINTER(c_ubyte)()
size = c_int()
Foo(byref(mem),byref(size))
print(size.value, mem[0], mem[1], mem[2], mem[3])
输出
4 0 1 2 3
【讨论】:
谢谢!隔离代码确实有效。很遗憾我没有自己隔离它并修补大型代码库。这是我的python代码中的一个错误,221被释放了记忆:) 谢谢!mem = POINTER(c_ubyte)()
末尾缺少括号。以上是关于Python 和 ctypes:如何正确地将“指针对指针”传递给 DLL?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 ctypes 将数组从 C++ 函数返回到 Python