【问题标题】:C Method returning string to Python via ctypesC方法通过ctypes将字符串返回给Python
【发布时间】:2018-08-18 21:29:08
【问题描述】:

几年前,我不得不为 C 库创建一个 python 包装器。我对 C 的了解非常有限,但我设法创建了所需的内容。 突然一种方法开始引起问题,我唯一的猜测是它必须与 python 更新有关。

无论如何,我有以下 C 代码:

const char * myFunction()
{
    return "My String";
}

DLL_EXPORT const char*
test()
{
    return myFunction();
}

在我的 Python 包装器中是使用以下方法调用的:

def test(self):
        ret = self.lib.test()

        return c_char_p(ret).value

如前所述,这运行良好,但考虑到我最近在尝试修复它时发现的情况,我不确定为什么。

目前我在调用 test() 方法时从 python 得到“Seg Fault”。

使用这个线程:

ctypes return a string from c function

When to use malloc for char pointers

我设法修复了我现在看起来像这样的代码,c:

const char * myFunction()
{
    return "My String";
}

DLL_EXPORT const char*
test()
{
    const char* st = myFunction();
    char *bar = _strdup(st);

    return bar;
}

python 代码保持不变。如前所述,我对 C 的了解非常有限,因此很少有问题:

  1. 知道为什么旧的实施正在工作并突然停止了吗?是否有一些可能影响它的 python 更新?
  2. 为什么在我的 c test() 函数中我必须执行 _strdup(st) 并返回 bar 而不是简单地返回 st?

【问题讨论】:

    标签: python c ctypes


    【解决方案1】:

    您使用的是 64 位 Python 吗? self.lib.test 的返回类型默认为 c_int,即 32 位。如果指针是 64 位的,则您正在截断指针。 您可能只是在代码更改中很幸运,_strdup 位于内存中的 4GB 以下。

    如果你声明:

    self.lib.test.restype = c_char_p
    

    那么这应该可以工作:

    def test(self):
        ret = self.lib.test()
        return ret.value
    

    【讨论】:

    • 是的,我正在使用 x64 Python。我现在拥有的新代码可以工作。 '更改 _strdup 位于内存中的 4GB 以下'是什么意思?
    • @stugal 您更改了 C 代码,但没有失败。但我认为你的指针被截断了,它可能在你的新情况下工作,只是因为指针地址恰好分配在 4Gb 以下,一个适合 32 位的地址。情况可能并非总是如此。正确的解决方案是将返回类型指定为指针,并保留 C 代码原来的样子。另外,strdup 版本存在内存泄漏。
    • 我将返回的类型转换为指针。另外,它是如何发生内存泄漏的?我的意思是,如果我不释放我在另一种方法中所做的内存(这是一个不同的主题)
    • @Stugal。铸造为时已晚。返回类型是 32 位 int,因此如果返回 64 位指针,它会在强制转换之前被截断为 32 位。正确设置返回类型。对于您的原始代码,您不需要释放指针,这是我对泄漏的评论,因为没有提到释放。
    猜你喜欢
    • 2021-04-27
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-05
    • 1970-01-01
    • 2011-11-15
    相关资源
    最近更新 更多