Pybind11 - где поставить PYBIND11_MODULE - PullRequest
0 голосов
/ 25 апреля 2018

Я сейчас немного поиграюсь с pybind11.Я пытаюсь создать класс C ++, который затем передается интерпретатору python, встроенному в мой исходный код C ++.

Я создал некоторый фиктивный класс просто для проверки основных функций. Я сохранил все в одном исходном файле.Этот подход скомпилирован и работает без проблем.

Теперь я разделил свой фиктивный класс Test на Test.h и Test.cpp

Test.h

#pragma once
#include<iostream>
#include"pybind11\pybind11.h"

namespace py = pybind11;

class Test
{
public:
    Test(const std::string &s);
    ~Test();

    void printStr();

private:
    std::string _s;
};

Test.cpp

#include "Test.h"

PYBIND11_MODULE(TestModule, m)
{
    py::class_<Test>(m, "Test") 
        .def(py::init<const std::string &>())
        .def("printStr", &Test::printStr); 
}


Test::Test(const std::string &s) : _s(s)
{

}
Test::~Test()
{

}

void Test::printStr()
{
    std::cout << "---> " << _s << std::endl;
}

main.cpp

#include"Test.h"

int main(int argc, char **argv)
{

    PyImport_AppendInittab("TestModule", PyInit_TestModule);
    Py_Initialize(); 

    PyRun_SimpleString("import TestModule");
    PyRun_SimpleString("t = TestModule.Test(\"str\")"); 
    PyRun_SimpleString("t.printStr()"); 
    Py_Finalize();

    getchar();

    return 1;
}

После помещения в класс Testв новый файл компилятор больше не может найти PyInit_TestModule (строка main.cpp: 6), поскольку он генерируется макросом PYBIND11_MODULE, который находится в файле Test.cpp (ошибка MSVS2017: C2065).

Я пытался вставить макрос PYBIND11_MODULE в Test.h.Однако это привело к ошибке компоновщика, которая говорила, что «_PyInit_TestModule» уже определен в main.obj (ошибка MSVS2017: LNK2005)

Помещение макроса PYBIND11_MODULE в файл main.cpp работает.Однако я чувствую, что это станет совершенно нечитаемым, как только вы поместите много пользовательских определений модулей в main.cpp или, что еще хуже, у вас будет несколько Python-Interpreter, запускаемых из разных исходных файлов, где вам нужно будет поместить одно и то же определение во всете файлы, которые будут беспорядочными и, скорее всего, превратятся в ошибку компоновщика.

Кто-нибудь из вас сталкивался с такой же проблемой и как вы ее решили?

1 Ответ

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

Я создал собственный файл для привязок и скомпилировал / связал его вместе с исходным файлом c ++.Таким образом:

1) Test.h + Test.cpp содержит только код C ++ вашего класса

2) Test-bindings.cpp содержит PYBIND11_MODULE и #include <Test.h>

3) Здание (с cmake).Из него вы получите файл PyTest.so , который вы можете загрузить в python.

# c++ libray
add_library(TestLib SHARED /path/to/Test.h /path/to/Test.cpp)

# bindings
add_subdirectory(pybind11) # you must have downloaded this repo
include_directories(/path-only/to/Test.h)
pybind11_add_module(PyTest SHARED /path/to/Test-bindings.cpp /path/to/Test.cpp)

4) (я предлагаю вам) написать основной в python, используяпривязка к python, которую вы только что создали

5) В вашем main.py

 import PyTest
 # do something
...