简体   繁体   English

无法使用 ctypes 从 python 读取“const char*”

[英]Cannot read 'const char*' from python using ctypes

I have a simple function in a c++ dynamic library which returns a const char* value.我在c++动态库中有一个简单的函数,它返回一个const char*值。 This value is assigned from a string type as shown in the code.该值是从string类型分配的,如代码所示。 I want to read the returned value of the function in a python script using ctypes :我想使用ctypes在 python 脚本中读取函数的返回值:

C++ C++

#include "pch.h"
#include <string>

#define EXPORT __declspec(dllexport)

extern "C" 
{
    EXPORT const char* sayHello()
    {
        std::string str = "hello world";
        const char* chptr = str.c_str();
        return chptr;
    }
}

Python Python

from ctypes import *

lib = CDLL("c:\\mysource\\mylib.dll")

lib.sayHello.restype = c_char_p

buff = lib.sayHello()

print(buff)

Using this code, in python I get as a result:使用此代码,在 python 中我得到的结果是:

b''

But when I change my cpp file and instead of using the string type and the conversion with c_str() , I assign the "hello world" directly into the const char* , it works ok:但是当我更改我的 cpp 文件而不是使用string类型和转换c_str() ,我将"hello world"直接分配给const char* ,它工作正常:

EXPORT const char* sayHello()
{
    const char* chptr = "hello world";
    return chptr;
}

... and I get as a result in python: ......我在python中得到了结果:

b'hello world'

Why when using a string variable, I receive an empty entry in python, but when using just the const char* , it works as expected?为什么在使用string变量时,我在 python 中收到一个空条目,但是当只使用const char* ,它按预期工作?

Your string is destructing as you reach the end of your function block - and the memory for the associated const char * is getting freed.当您到达功能块的末尾时,您的字符串正在破坏 - 相关联的const char *的内存正在被释放。

    EXPORT const char* sayHello()
    {
        std::string str = "hello world";
        const char* chptr = str.c_str(); // points to memory managed by str
        return chptr; // str gets destructed! This pointer points to dealloced memory
    }

In your other example, the const char * points to a string literal, which is likely in the .rodata segment, and so will outlive the scope of the function.在您的另一个示例中, const char *指向一个字符串文字,它可能在 .rodata 段中,因此将超过函数的范围。

EXPORT const char* sayHello()
{
    const char* chptr = "hello world"; // String literal
    return chptr; // Underlying memory isn't deallocated
}

Both versions are wrong because the memory will be released once the sayHello function has finished.两个版本都是错误的,因为一旦sayHello函数完成,内存就会被释放。

If you need to return a string you have 2 options:如果您需要返回一个字符串,您有 2 个选项:

  1. Create a buffer from python first using ctypes.create_string_buffer and copy the data to it through strcpy首先使用ctypes.create_string_buffer从 python 创建一个缓冲区,然后通过strcpy将数据复制到它
  2. Use malloc or something to reserve the memory without releasing it.使用malloc什么的来保留内存而不释放它。 In this case you have to manually run free once you're done or you'll have a memory leak.在这种情况下,您必须在完成后手动free运行,否则会出现内存泄漏。

I would strongly recommend option 1.我强烈推荐选项 1。

Option 1 would look something like this:选项 1 看起来像这样:

#include "pch.h"
#include <string>

#define EXPORT __declspec(dllexport)

extern "C" 
{
    EXPORT void sayHello(char* buffer, int bufferSize)
    {
        std::string str = "hello world";
        str.copy(buffer, bufferSize);
    }
}
from ctypes import *

lib = CDLL("c:\\mysource\\mylib.dll")

lib.sayHello.restype = c_char_p

buffer_size = 32
buffer = create_string_buffer(buffer_size)
lib.sayHello(buffer, buffer_size)

print(buffer.value)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM