Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to convert cython generated C language code to executable file

Tags:

python

c

gcc

cython

I am using windows operating system. I have visual studio and all the build tools associated with it. I have simple python script. I used cython to generate a "C" file. I am trying to convert this C file to an executable. I do not want to use any other modules like pyinstaller, py2exe or cxFreeze.

The conversion from .py to C was successful. However sadly I am getting some errors while converting this C file to an executable.

Could anyone please help me ? I have checked various other questions on this issue and none of have them have this issue.

This is my (.pyx script)

from tkinter import Tk

root = Tk()
root.mainloop()

I used this following command in CMD to build a C extension for this script:

python setup.py build_ext --inplace -DMS_WIN64

Then I am using this command in CMD to build an executable:

gcc -DMS_WIN64 C:/Users/Siva/Desktop/Scripts/TEST/test.c -IC:/"Program Files"/Python37/include -LC:/"Program Files"/Python37/libs -lpython37 -o output

This produces the following error:

C:\Users\Siva\Desktop\Scripts\TEST>gcc -DMS_WIN64 C:/Users/Siva/Desktop/Scripts/TEST/test.c -IC:/"Program Files"/Python37/include -LC:/"Program Files"/Python37/libs -lpython37.a -o output
C:/Users/Siva/Desktop/Scripts/TEST/test.c:213:41: warning: division by zero [-Wdiv-by-zero]
     enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
                                         ^
C:/Users/Siva/Desktop/Scripts/TEST/test.c:213:12: error: enumerator value for '__pyx_check_sizeof_voidp' is not an integer constant
     enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
            ^~~~~~~~~~~~~~~~~~~~~~~~

I have attached a screenshot of the error below

enter image description here


2 Answers

Finally After a long eternal struggle I have found the solution. Thanks to Joshua for the great support.

There is a small modification in the .PYX code. It appears like we must define everything within a function so that when the code gets converted to C language, it has a main function in it.

So the first step is the .PYX is edited as:

from tkinter import Tk

cdef public void function():
    root = Tk()
    root.mainloop()

if __name__ == "__main__":
    function()

Then I used the following command to generate the header file (.h) and the C program file

python -m cython test.pyx --embed

This is the trick:

Go to the C program file that was generated and search for the wmain function and remove the "w" from it. Or you could just Ctrl + F search for wmain and replace its instances with main.

For exmaple in my program there was only one wmain instance. I changed it to main. It look something like the code shown below. Just change the wmain to main.

#if PY_MAJOR_VERSION < 3
int main(int argc, char** argv) {
#elif defined(WIN32) || defined(MS_WINDOWS)
int wmain(int argc, wchar_t **argv) 

Then I used the GCC command to generate the executable. The command is as follows. I do not understand why it works. But it does.

x86_64-w64-mingw32-gcc-8.1.0 -mconsole -DSIZEOF_VOID_P=8 -DMS_WIN64 C:/Users/Siva/Desktop/Scripts/CYTHON/test.c -IC:/"Program Files"/Python37/include -LC:/"Program Files"/Python37/libs -lpython37 -o output

I only wish someone would explain why approach works.

Environmental check failed; probably autodetect is broken. Try one of the following to override it:

gcc -DSIZEOF_VOID_P=8 -DMS_WIN64 ...

gcc -DSIZEOF_VOID_P=4 ...

Where the 8 constant is for 64 bit output and the 4 constant is for 32 bit output. It's most likely that you configured for 64 bit and actually invoked the 32 bit gcc. If so, the following invocation should work assuming the 64 bit targeting gcc is also installed.

x86_64-w64-mingw32-gcc -DSIZEOF_VOID_P=8 -DMS_WIN64 ...
like image 42
Joshua Avatar answered Oct 27 '25 05:10

Joshua