Создание общего объекта из одного .cpp - PullRequest
0 голосов
/ 27 июня 2018

Я пытаюсь создать библиотеку общих объектов из файла cpp, который представляет собой простой набор функций. Я хочу использовать ctypes для взаимодействия с питоном.

Скажите, у меня есть файл cpp:

#include "print.h"
#include <vector>
#include <iostream>
#include <dlfcn.h>

void print_array(const std::vector<std::vector<float>> &A){
  for(size_t i = 0; i < A.size(); i++) {
    for(size_t j = 0; j < A[0].size(); j++) {
      std::cout << A[i][j] << "\n";
    }
  }
}

и заголовочный файл

#ifndef ADD_H
#define ADD_H
#include <vector>

void print_array(const std::vector<std::vector<float>> &A);

#endif

Я пытался построить

g++ -fpic -c print.cpp -o print.o
g++ -shared -o print.so print.o

Тогда в питоне

from cytpes import cdll
print_lib = cdll.LoadLibrary("print.so")

линия

print_lib.print_array()

выходы * * тысяча двадцать-одны

AttributeError: ./print.so: undefined symbol: print_array

nm -D print.so

дает вывод

0000000000201060 B __bss_start
                 U __cxa_atexit
                 w __cxa_finalize
0000000000201060 D _edata
0000000000201068 B _end
0000000000000c14 T _fini
                 w __gmon_start__
0000000000000898 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000000a50 T _Z11print_arrayRKSt6vectorIS_IfSaIfEESaIS1_EE
0000000000000bcc W _ZNKSt6vectorIfSaIfEE4sizeEv
0000000000000bf2 W _ZNKSt6vectorIfSaIfEEixEm
0000000000000b6a W _ZNKSt6vectorIS_IfSaIfEESaIS1_EE4sizeEv
0000000000000ba2 W _ZNKSt6vectorIS_IfSaIfEESaIS1_EEixEm
                 U _ZNSolsEf
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc

Что я в основном делаю неправильно на этапе компиляции?

1 Ответ

0 голосов
/ 27 июня 2018

Вы вызываете функцию C ++, в то время как ctypes ожидает связывания функций C:

  • Функции C имеют другое (т.е. ни одного) искажение имени, как вы заметили
  • Функция C не может иметь параметры C ++ (объекты std, такие как std :: vector, ссылки и т. Д.)

Чтобы решить вашу проблему, объявите чистый API-интерфейс в стиле C в ваших заголовках, и если вы собираетесь реализовать функции в C ++ и использовать g ++ в качестве компилятора / компоновщика, вы должны добавить объявление extern "C" прямо перед функцией объявление в заголовочном файле или в виде блока вокруг ваших объявлений:

extern "C" void print_array(...);

Это предотвратит искажение имени в C ++.

Использование векторов и других типов C ++ в функциях интерфейса вызовет проблемы с ABI, т.е. е. «это не сработает», даже если все ссылки и компиляции выглядят чисто.

Используйте функции C с типами данных, поддерживаемыми ctypes (см. Документы Python по ctypes ), в своих функциях в качестве интерфейса, не стесняйтесь реализовать в C ++, но затем оберните объявления функций C в extern "C" блок для предотвращения искажения имени.

Пожалуйста, обратитесь к документации по ctypes, чтобы узнать, как правильно использовать структуры, объединения, ссылки и т. Д. В качестве параметров функций, так как есть много подводных камней и проблем, которые необходимо учитывать.

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