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

如何像 python ctypes 那样指定 JNR 指针

如何使用 ctypes 在 python 中查看指针值的变化

Python ctypes:如何释放内存?获取无效指针错误

Python ctypes:如何释放内存?获取无效指针错误

如何正确地将对象/指针存储到 Qlist 中