Вызвать функцию C ++ из python и получить возвращаемое значение - PullRequest
3 голосов
/ 13 июля 2020

Я пытаюсь вызвать функцию C ++ из сценария python. Вот мой пример кода C ++ и Python.

strfun c. cpp

#include <iostream>
#include <string>

using namespace std;

string getString()
{
    string hostname = "test.stack.com";
    return hostname;
}

strfun c .py

import ctypes

print(ctypes.CDLL('./strfunc.so').getString())

Я скомпилировал и сгенерировал общую библиотеку из моей программы на C ++, используя следующую команду:

g++ -fPIC strfunc.cpp -shared -o strfunc.so

Когда я пытаюсь выполнить strfun c .py, он дает следующая ошибка:

$ ./strfunc.py 
Traceback (most recent call last):
  File "./strfunc.py", line 5, in <module>
    print(ctypes.CDLL('./strfunc.so').getString())
  File "/usr/lib64/python3.7/ctypes/__init__.py", line 372, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib64/python3.7/ctypes/__init__.py", line 377, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: ./strfunc.so: undefined symbol: getString

Пожалуйста, помогите мне узнать, как я могу решить эту проблему. То же самое работает с функцией int.

1 Ответ

1 голос
/ 13 июля 2020

Если вы используете readelf -Ws в своем файле so, он предоставит вам элементы внутри вашей библиотеки so:

FUN C GLOBAL DEFAULT 12 _Z9getStringB5cxx11v

Вы увидите, что ваша функция действительно существует, просто у нее искаженное имя. Таким образом, правильное имя для вызова ctype в библиотеке будет _Z9getStringB5cxx11v ().

Однако с этим все еще есть несколько ошибок. Отметьте свой метод как внешний, чтобы компилятор знал, что у него есть внешняя связь:

extern string getString()

В качестве альтернативы, если вы хотите использовать его как getString (), вы можете пометить его как extern «C», что отключит C ++ mangler

extern "C" string getString()

Но в любом случае, я думаю, вы обнаружите, что у вас есть проблемы с памятью. Я думаю, что правильным способом было бы вернуть указатель стиля c на массив символов и управлять им самостоятельно, что-то вроде этого должно работать:

strfun c. cpp:

#include <iostream>
#include <string>

using namespace std;

char hostname[] = "test.stack.com";

extern "C" char * getString()
{

        return hostname;

}

strfun c .py:

#!/usr/bin/env python
from ctypes import *

test=cdll.LoadLibrary("./strfunc.so")
test.getString.restype=c_char_p
print(test.getString())

В случае строки, я думаю, вам нужно выяснить, как правильно управлять памятью и типами возврата, чтобы сообщить python, что вы фактически передающая строка. Это может быть выполнимо, но не так просто, как указано выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...