简体   繁体   中英

SWIG + Python without DLL

For the past few days I've been struggling importing a SWIG-generated module. I'm using Python 3.4.1 with SWIG 3.0.5.

I've setup my interface API.i file as follows:

%module Root
%{
#include "Root.h"
%}
%include "Root.h"

Nothing fancy in the header, as I'm just trying to get something going. A API_wrap.cxx file is generated and so is a Root.py file. So far so good.

Now, based on the following site: https://docs.python.org/2/faq/windows.html#how-can-i-embed-python-into-a-windows-application they imply that I can load the module directly (all in the same EXE, without the need to have a separate DLL) by doing the following:

Py_Initialize();
PyInit__Root();
PyRun_SimpleString("import Root");

The import works fine if I don't have a Root.py file still, but then I lose the shadow/proxy class (among other things, I'm guessing). If I do have the Root.py file, I get the following error:

"Import can't find module, or can't find name in module."

I notice if I write gibberish in the Root.py file, I get a syntax error, which makes it pretty evident that the generated Root.py is problematic. I imagine there's some sort of setup I've done wrong, but if anyone has any suggestions, they would be appreciated!

I think you'll want to use PyImport_AppendInittab to register the builtin module properly.

You'll also want to call PySys_SetPath() to set the path to the Python proxy part of the module itself.

I put together a complete example for you. With the SWIG module:

%module test

%inline %{
void doit(void) {
  printf("Hello world\n");
}
%}

Which we can compile and validate standalone using:

swig2.0 -Wall -python test.i
gcc -Wall -Wextra -shared -o _test.so test_wrap.c -I/usr/include/python2.7
Python 2.7.6 (default, Mar 22 2014, 22:59:38) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.doit()
Hello world

We can then write our C code to embed Python. (I used my answer to this question as a reference point). My C for this test was:

#include <Python.h>
void init_test(void);

int main() {
  PyImport_AppendInittab("_test", init_test); // Register the linked in module
  Py_Initialize();
  PySys_SetPath("."); // Make sure we can find test.py still
  PyRun_SimpleString("print 'Hello from Python'");
  PyRun_SimpleString("import test");
  PyRun_SimpleString("test.doit()");
  return 0;
}

This worked when compiled and run:

swig2.0 -Wall -python test.i
gcc -Wall -Wextra -shared -c -o test_wrap.o test_wrap.c -I/usr/include/python2.7
gcc run.c test_wrap.o -o run -Wall -Wextra -I/usr/include/python2.7 -lpython2.7
./run
Hello from Python
Hello world

If I skipped either setting the path or the AppendInittab call it didn't work as I'd hoped.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM