What are the next step after compiling PYBIND11_MODULE in C++ file

只谈情不闲聊 提交于 2020-08-10 19:02:18

问题


I was trying to use PYbind 11 to wrap the following small C++ test programme into a Python module, so I can call the test C++ function from python files. My problem is : while the C++ file compiled successfully, I have no clue as to what steps to take next to import the newly created module file in python. I tried to run "from example import add" in a test Python file in Spyder but received error message saying there is no module named example. I'm using Windows10 (x64bit), Python3.7 and Visual studio 2017 community. Can some one please help? Thank you very much!

#include
//#include <Aspose.Cells.h>
#include <pybind11/pybind11.h>

void print(const char*);

int add(int i, int j) {
return i + j;
}

PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring

m.def("add", &add, "A function which adds two numbers");
}

int main()
{
const char *x = "C Plus plus is wonderful.";

char *z;
char b = 'z';
z = &b;

int num = 10;
int* a = 0;

print(x);
}

void print(const char* z)
{

std::cout << "pointer z is" << z << "\n";

std::cin.get();
}

UPDATE: I followed Stuart's suggestion below when building my test c++ programme. I made two attempts: at the first attempt, I changed Target Extension to ".pyd"; whereas at the second attempt, I kept Target Extension as "dll".

In both attempts, I received the same error message from Visual Studio, which seem to suggest that the DLL file being built can not be started (as shown in the screenshot that immediately follows) Error Messages for Starting DLL Programme However, the actual building of dll file seemed successful, as I can see one dll file and one Python Extension Module file, with filenames and path listed as follows: C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug\ConsoleApplication5.dll and C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug\ConsoleApplication5

The Visual Studio output message upon building is pasted at the end.

My problem is: I created a Test.py file in the same directory (C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug) and tried to run it in Spyder after including just one line command "import example ". Sypder returned a error message saying " No MODULE Named Example".

Can anyone please help? Thanks a lot!

1>------ Build started: Project: ConsoleApplication5, Configuration: Debug x64 ------
1>LINK : C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug\ConsoleApplication5.dll not found or not built by the last incremental link; performing full link
1>   Creating library C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug\ConsoleApplication5.lib and object C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug\ConsoleApplication5.exp
1>ConsoleApplication5.vcxproj -> C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug\ConsoleApplication5.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

UPDATE2: I followed every details of Stuart's instructions in his Update2. I got example.pyd (as shown in the following screenshot) However, I got error message when running in Spyder, as follows: (Sorry I only managed to copy the second half of Spyder output message as its very hard to do text selection in Spyder console)

File "C:\Users\rmili\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:/Users/rmili/source/repos/ConsoleApplication5/x64/Debug/Test.py", line 9
    d = "C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug"
       ^
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape

I changed backward slash "" to forward slash"/" in the value that's being assigned to "d", and got the following error again:

File "C:\Users\rmili\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:/Users/rmili/source/repos/ConsoleApplication5/x64/Debug/Test.py", line 12, in <module>
    import example

ModuleNotFoundError: No module named 'example'

UPDATE3: As shown in the following screenshot, example module can not be found in Windows command line prompt. [Unable to find example module in Windowscommand line prompt]3


回答1:


Make sure the compiled output file is named example.pyd (or has a symlink of that name pointing to it), and try running python from the same directory.


Update: How to build a .pyd in Visual Studio

On Windows, compiled Python modules are simply DLL files, but they have a .pyd file extension. You mentioned that your C++ file compiles successfully. Did you compile it as an executable (.exe), or as a .dll? You should compile it as a DLL, but change the file extension to .pyd.

The Visual Studio documentation explains how to change your project to create a DLL. Here's what it says:

  1. Open the project's Property Pages dialog box. For details, see Set C++ compiler and build properties in Visual Studio.

  2. Click the Configuration Properties folder.

  3. Click the General property page.

  4. Modify the Configuration Type property.

Also, on that same settings page, you can find an option to change the Target Extension property. Change it to .pyd. (Or simply rename the file yourself after it is built.)


Update 2

I think you need to change three settings:

  • Target Name
    • Change to example
  • Target Extension
    • Change to .pyd
  • Configuration Type
    • Change to Dynamic Library (.dll)

Also, I recommend deleting (or commenting out) everything from example.cpp except for the code shown below. (I don't know if the presence of a main() function may cause problems, so just remove it.)

After that, building your project should produce the following file:

C:\Users\rmili\source\repos\ConsoleApplication5\x64\Debug\example.pyd

Than, from the Spyder console, try this:

import os

d = "C:\\Users\\rmili\\source\\repos\\ConsoleApplication5\\x64\\Debug"
os.chdir(d)

import example
example.add(1,2)

I don't have a Windows machine to test with. But in case it's useful, here's how I compiled your example on my Mac. (On Mac and Linux, they use the extension .so instead of .pyd.)

// example.cpp
#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example plugin";

    m.def("add", &add, "A function which adds two numbers");
}
$ # Compile
$ clang++ -I${CONDA_PREFIX}/include -I${CONDA_PREFIX}/include/python3.7m -undefined dynamic_lookup -shared -o example.so example.cpp

$ # Test
$ python -c "import example; print(example.add(10,20))"
30



回答2:


I have found answer to my problem:

  1. Make sure all steps I described previously in my post are done
  2. this is what I missed -` It is important to make sure the file type of "example" is Python Extension Module, as shown in the following screenshot . As shown in screenshots of my Updates, initially the Type of my "example.pyd" file was just "File". I managed to convert it to Python Extension Module by adding "cp35-win_amd64." in the file extension, resulting in file name "examplelib.cp35-win_amd64.pyd", and then remove the same texts that were added.


来源:https://stackoverflow.com/questions/63054260/what-are-the-next-step-after-compiling-pybind11-module-in-c-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!