1

What I try to achieve is compiling my Python script to lib/dll and invoke it with arguments.

This is my setup.py file for the script:

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("nu3k2nu4k.py")
)

Used this command to produce compilation outputs:

python setup.py build_ext --inplace

following files produced:

nu3k2nu4k.c
nu3k2nu4k.cp36-win_amd64.pyd
nu3k2nu4k.pyx

and a subdirectory named build which contains:

nu3k2nu4k.cp36-win_amd64.exp
nu3k2nu4k.cp36-win_amd64.lib
nu3k2nu4k.obj

How can I invoke the compiled script from c++ code with arguments?

I used Cython for the task but that's not mandatory, boost or others could be used as well (I'm doing this to make the source code not accessible).

Edit:

Using the documentation provided by Mykola Shchetinin I have managed to generate an API header file for my script. I basically added a cdef api keyword to my main function. While this does help me export the method name to c++ I still need a way to pass around some arguments to my script. Since I pass string arguments I was hoping for a similar way like using PyRun to set argv and parse the arguments from the script (since I would like to avoid conversion of strings from c to python encoding if possible) Is there any easy way to pass those string arguments?

EDIT 2:

I got it working! following the sample provided by Mykola and directly compiling the c file output instead of using the .lib I got it working.

5
  • 1
    It is actually in the docs: cython.readthedocs.io/en/latest/src/userguide/… Commented Oct 15, 2017 at 8:43
  • From the documentation it seems like I need to add a cdef api keyword to my main function in order to produce the header file needed. I'll give it a shot... Commented Oct 15, 2017 at 9:29
  • 1
    I managed to create an API header file for my script. Is there any way to set the the arguments like in PyRun? declaring the arguments as c types seems like a one ugly way for dealing with conversions from c strings to python and I would like to avoid that if possible... Commented Oct 15, 2017 at 10:13
  • I suggest you updating your question with what you achieved to make it easier to answer for other users. I have just pointed out what I have found in the docs... Commented Oct 15, 2017 at 10:16
  • Sure, just edited my question with my progress. thanks! Commented Oct 15, 2017 at 10:25

1 Answer 1

1

I have tried to do that by myself. So I convert char * to bytes in cython. (according to docs)

That is what I came up with. I have the following setup (gcc and centos7.2):

setup.py

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("func.pyx")
    )

main.c

#include "Python.h"
#include "func.h"

int main() {
    Py_Initialize();
    initfunc();
    func("0123hello jorghy!!");
    Py_Finalize();
    return 0;
}

func.pyx

cdef public func(char * arg):
    cdef bytes py_bytes = arg
    print(str(py_bytes));

I build all this stuff with the following commands:

python setup.py build_ext --inplace

gcc -I/usr/include/python2.7 -lpython2.7 -Wall -Wextra -O2 -g -o test main.c func.c

Then when running the executable file test I get the following results:

0123hello jorghy!!

UPDATE

There is another way to approach this problem:

I have created a cython file test.pyx:

import sys

if __name__ == "__main__":
    print("hei")
    print(sys.argv)

And compiled as an executable it using commands:

cython test.pyx --embed
gcc -I/usr/include/python2.7 -lpython2.7 -Wall -Wextra -O2 -g -o test test.c

Then you can call this code as an executable file:

$ ./test 1 2 3
hei
['./test', '1', '2', '3']

Then you can call it from C++ using std::system or other (better) methods.

Sign up to request clarification or add additional context in comments.

5 Comments

The behaviour is the same when I do not use str() call inside print()
I have tried to follow this example and did the same for me. I have created same setup.py and func.pyx and compiled it the same for the first method. I used this code to invoke the function: Py_Initialize(); PyInit_func(); func("0123hello jorghy!!"); Py_Finalize(); I linked visual studio with the libary file produced from Cython and there was a linkage compilation error. the method signature was not exported to the lib file. When I tried to do similar method with api keyword instead of public it did compile but I got an exception. Thanks for the help with this.
I'm trying to solve the exception/ compilation error in visual studio. I'll update what I got soon.
Probably something regarding Python.h, python2.7 libraries. I had to add -I/usr/include/python2.7 -lpython2.7 arguments to my gcc compiler to avoid linkage errors (I use centos7.2). There should be something similar for visual studio C++ compiler on stackoverflow.
Ok! so I got it working when instead of using the lib file produced by Cython I did the same as you and directly compiled the .c file output. I got it working for a small sample project so I'll implement it in my project as well in no time. I have marked your answer as accepted, thanks for all the help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.