PyBind11 с SystemC с использованием CMake: ImportError
Я работаю с проектом SystemC, в который я хотел бы добавить привязки Python, используя PyBind11, и я следовал документации на сайте, чтобы написать привязки.
Я использую 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 ответа
Это потому, что общая библиотека SystemC требует sc_main
функция.
Вы должны попробовать связать со статической библиотекой (libsystemc-2.3.2.a
).
Это может быть связано с тем, что 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.