CTYPES和PYTHON3:无法返回长字符串 [英] CTYPES and PYTHON3: Can't return long string

查看:280
本文介绍了CTYPES和PYTHON3:无法返回长字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C ++代码,为此我创建了一个python.ctypes包装器。它工作得很好,除非返回的字符串很长。 C代码示例:

I have a C++ code for which I created a python.ctypes wrapper. It works quite well, except when the returning string is long. Example of C code:

extern "C" {

const char * hallo(char * nome)
{
    string str(nome);
    str = "hallo " + str;

    for(int i=0; i<100; i++)
        str += " new content";

    return str.c_str();
}

我的python代码是:

My python code is:

self.lib = ctypes.CDLL(LIB_PATH)
self.lib.hallo.restype = ctypes.c_char_p
self.lib.hallo.argtypes =[ctypes.c_char_p]
j = self.lib.hallo('my name'.encode())
print('INIT: ' + j.decode())

字符串大小是动态的(实际上,它将是一个json字符串)。解决这种情况的最佳方法是什么?

The string size is dynamic (in fact, it will be a json string). What is the best way to deal with this situation?

非常感谢。

推荐答案

这里的问题是,当您返回str.c_str()时,您将返回指向堆栈分配内存的指针,该指针在从C ++代码返回时将被覆盖。

The issue here is that when you return str.c_str() you're returning a pointer to stack allocated memory which gets overwritten on return from the C++ code.

可能的解决方法是使用静态字符串str ,例如:

Potential workarounds are to use static string str such as:

#include <string>
#include <sstream>

extern "C" {

const char * hallo(char * nome)
{
    static std::string str;
    std::stringstream stream;
    stream << "hallo " << nome;

    for(int i=0; i<100; i++)
        stream << " new content";

    str = stream.str();
    return str.c_str();
}

}

尽管这样做会阻止您打电话

Although this will prevent you from calling the routine from multiple threads.

如果希望能够从多个位置调用该例程,则可能应该将参数指针指向某个内存,然后传递一个指针由 ctypes.create_string_buffer 创建的缓冲区(希望在这种情况下具有合适的大小)。

If you want to be able to call it from multiple places, you should probably take a parameter pointer to some memory, and pass in a pointer buffer created from ctypes.create_string_buffer (hoping that it has the right size in this case).

例如:

#include <string>
#include <sstream>

extern "C" {

const char * hallo(char * nome, char *writebuffer, unsigned int buffersize)
{
    std::string str(nome);
    str = "hallo " + str;

    for(int i=0; i<100; i++)
        str += " new content";

    if (str.size() < buffersize) {
        str.copy(writebuffer, buffersize);
        return writebuffer;
    } else {
        return 0;
    }
}

}

然后一些使用该库的示例python代码;传入128k缓冲区(已更新python 3):

Then some sample python code that uses this library; passing in a 128k buffer (python 3 updated):

import ctypes

lib = ctypes.CDLL(LIB_PATH)
lib.hallo.restype = ctypes.c_char_p
lib.hallo.argtypes =[ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint]
allocation = ctypes.create_string_buffer(128 * 1024)
j = lib.hallo('my name'.encode(), allocation, 128 * 1024)
if j is not None:
    print('INIT: ' + j.decode("UTF-8"))
else:
    print("Buffer was too small")

这篇关于CTYPES和PYTHON3:无法返回长字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆