如何通过指针回到ctypes的?(How to pass pointer back in ctype

2019-08-04 05:04发布

不知道很多关于ctypes的,最近刚开始使用它。

我在类C的dll一个简单的函数返回一个指向动态生成的字符串。
它工作正常,但是,因为我手动分配内存的字符串,我应该在使用后释放它。

我有这样的事情:

extern "C" char* DLL_EXPORT func(const char* str1, const char* str2)
{
    return getSomeString(str1, str2);
}

// Goal is to call this function correctly from Python.    
extern "C" void DLL_EXPORT freeMem(void *mem)
    {
        if(mem!=NULL)
            delete mem;
    }

但我没有任何想法,我怎么可以通过在Python收到指针回来进行删除吗?

Answer 1:

你在正确的轨道上。

// TestDLL.cpp
#include <string.h> // strcpy

extern "C" __declspec(dllexport) char* stringdup(const char* str) {
    char* p = new char[strlen(str)+1];
    strcpy(p,str);
    return p;
}

// if you have no good reason to use void*, use the type
// you've allocated. while it usually works for built-in
// types, it wouldn't work for classes (it wouldn't call
// the destructor)
extern "C" __declspec(dllexport) void stringfree(char* ptr) {
    // you don't need to check for 0 before you delete it,
    // but if you allocate with new[], free with delete[] !
    delete [] ptr; 
}

而在蟒蛇:

# Test.py
import ctypes

lib = ctypes.cdll.TestDLL

# this creates a c-style char pointer, initialized with a string whose
# memory is managed by PYTHON! do not attempt to free it through the DLL!
cstr = ctypes.c_char_p("hello ctypes")

# call the dll function that returns a char pointer 
# whose memory is managed by the DLL.
p = lib.stringdup(cstr)

# p is just an integer containing the memory address of the 
# char array. therefore, this just prints the address:
print p

# this prints the actual string
print ctypes.c_char_p(p).value

# free the memory through the DLL
lib.stringfree(p)


Answer 2:

通常,每次在使用功能ctypes应该有它的参数和返回类型声明所以Python可以检查正确的参数数量和类型转换Python对象参数传递给正确的C数据对象。 不幸的是在这种情况下,正常的返回值funcc_char_p ,但ctypes尝试是有益的,一个转换c_char_p返回值到Python字符串,还能访问原始的C指针值。 相反,你可以声明返回类型c_void_p和使用cast检索字符串值,其离开返回值的c_char_p对象。

下面是一个示例(Python 3):

import ctypes

func = ctypes.cdll.TestDLL.func
func.argtypes = [ctypes.c_char_p,ctypes.c_char_p]
func.restype = ctypes.c_void_p

freeMem = ctypes.cdll.TestDLL.freeMem
freeMem.argtypes = [ctypes.c_void_p]
freeMem.restype = None

s = func(b'abcdef',b'ghijkl')
s = ctypes.cast(s,ctypes.c_char_p)
print(s.value)
freeMem(s)


文章来源: How to pass pointer back in ctypes?