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
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 ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With