PyBind11 с SystemC с использованием CMake: ImportError - PullRequest
0 голосов
/ 19 ноября 2018

Я работаю с проектом SystemC, в который я хотел бы добавить привязки Python, используя PyBind11, и я следовал документации на сайте здесь , чтобы написать привязки.
I 'Я использую CMake для создания своего проекта, и проблема, с которой я сталкиваюсь, заключается в том, что мне нужно связать свой код C ++ с SystemC, а также с PyBind11.Вот как в настоящее время выглядят мои CMakeLists:

project(simple_fifo_python)
cmake_minimum_required(VERSION 3.0)

find_package(pybind11 CONFIG REQUIRED)
message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}")

find_library(SC_LIB systemc $ENV{SYSTEMC_HOME}/lib-linux64 REQUIRED)

pybind11_add_module (simple_fifo_python simple_fifo.cpp)
target_compile_options(simple_fifo_python PUBLIC  -Wall)
target_include_directories(simple_fifo_python PUBLIC $ENV{SYSTEMC_HOME}/include)
target_link_libraries(simple_fifo_python PUBLIC ${SC_LIB})

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

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <systemc.h>

class write_if : virtual public sc_interface
{
   public:
     virtual void write(char) = 0;
     virtual void reset() = 0;
};

class read_if : virtual public sc_interface
{
   public:
     virtual void read(char &) = 0;
     virtual int num_available() = 0;
};

class fifo : public sc_channel, public write_if, public read_if
{
   public:
     fifo(sc_module_name name) : sc_channel(name), num_elements(0), first(0) {}

     void write(char c) {
       if (num_elements == max)
         wait(read_event);

       data[(first + num_elements) % max] = c;
       ++ num_elements;
       write_event.notify();
     }

     void read(char &c){
       if (num_elements == 0)
         wait(write_event);

       c = data[first];
       -- num_elements;
       first = (first + 1) % max;
       read_event.notify();
     }

     void reset() { num_elements = first = 0; }

     int num_available() { return num_elements;}

   private:
     enum e { max = 10 };
     char data[max];
     int num_elements, first;
     sc_event write_event, read_event;
};

class producer : public sc_module
{
   public:
     sc_port<write_if> out;

     SC_HAS_PROCESS(producer);

     producer(sc_module_name name) : sc_module(name)
     {
       SC_THREAD(main);
     }

     void main()
     {
       const char *str =
         "This can really work with pybind11 yo peeepalsssssss!\n";

       while (*str)
         out->write(*str++);
     }
};

class consumer : public sc_module
{
   public:
     sc_port<read_if> in;

     SC_HAS_PROCESS(consumer);

     consumer(sc_module_name name) : sc_module(name)
     {
       SC_THREAD(main);
     }

     void main()
     {
       char c;
       cout << endl << endl;

       while (true) {
         in->read(c);
         cout << c << flush;

         if (in->num_available() == 1)
       cout << "<1>" << flush;
         if (in->num_available() == 9)
       cout << "<9>" << flush;
       }
     }
};

class top : public sc_module
{
   public:
     fifo *fifo_inst;
     producer *prod_inst;
     consumer *cons_inst;

     top(sc_module_name name) : sc_module(name)
     {
       fifo_inst = new fifo("Fifo1");

       prod_inst = new producer("Producer1");
       prod_inst->out(*fifo_inst);

       cons_inst = new consumer("Consumer1");
       cons_inst->in(*fifo_inst);
     }
};

int sc_main (int, char *[]) {
   top top1("Top1");
   sc_start();
   return 0;
}

namespace py = pybind11;
using namespace pybind11::literals;

PYBIND11_MODULE(test, m) 
{
    m.doc() = "pybind11 test plugin with sysc support"; // optional module docstring
    py::class_<fifo>(m, "fifo")
        .def(py::init<sc_module_name>())
        .def("write", &fifo::write)
        .def("read", &fifo::read)
        .def("reset", &fifo::reset)
        .def("num_available", &fifo::num_available)
        .def_property("num_elements", &fifo::reset, &fifo::num_available);
    py::class_<producer>(m, "producer")
        .def(py::init<sc_module_name>())
        .def("main", &producer::main);
    py::class_<consumer>(m, "consumer")
        .def(py::init<sc_module_name>())
        .def("main", &consumer::main);
    py::class_<top>(m, "top")
        .def(py::init<sc_module_name>());

    m.def("sc_main", [](std::vector<std::string> args)
    {
        std::vector<char *> cstrs;
        cstrs.reserve(args.size());
        for (auto &s : args) cstrs.push_back(const_cast<char *>(s.c_str()));
        return sc_main(cstrs.size(), cstrs.data());
    });
}

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

(py37) mayank@b101l:~/test/pybindmod/simple_fifo$ python
Python 3.7.1 (default, Oct 23 2018, 19:19:42) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import simple_fifo_python
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /home/mayank/tools/lib-linux64/libsystemc-2.3.2.so: undefined symbol: sc_main
>>> 

Это мой первый проект, работающий с PyBind и CMakeLists с несколькими зависимостями, поэтому я не могу понять, гдеэта ошибка исходит от.Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Это может произойти из-за того, что C ++ искажает символ sc_main, который требуется и ожидается библиотекой systemc в формате символа C. Можете ли вы попробовать добавить extern "C" перед sc_main? Что-то вроде

extern "C" int sc_main (int, char *[]) {
   top top1("Top1");
   sc_start();
   return 0;
}

Это или перемещение функции sc_main в отдельный файл * .c.

0 голосов
/ 21 ноября 2018

Это связано с тем, что для общей библиотеки SystemC требуется функция sc_main.

Вам следует попытаться установить связь со статической библиотекой (libsystemc-2.3.2.a).

...