I tried together with a colleague to convert a Python file to a C file via Cython. Afterwards, we tried to make out of the C file a DLL. However, this doesn't work and the initialization of the Python file failed.
For completeness here is my code and the steps I performed:
Python File: hello.pyx
cdef public int sayHello ():
print("hello out there")
cdef int a = 5
return a
To create a C file out of the hello.pyx we used the following command in the Terminal:
Cython -3 hello.pyx
Then a hello.h file and a hello.c file are created. The hello.c file contains a lot of code and I am a very, very beginner in programming with C. Therefore I do not understand exactly everything what happens in there. My colleague supported me in making the changes in the following files.
To make the methods accessible in a DLL we added in the hello.c file at the end:
__declspec(dllexport) int Py_sayHello()
{
return __Pyx_PyInt_As_int(sayHello());
}
and replaced the methods in the hello.h file through:
#ifndef __PYX_HAVE__hello
#define __PYX_HAVE__hello
#include "Python.h"
extern "C"
{
__declspec(dllexport) int Py_sayHello();
__declspec(dllexport) void Py_init();
}
#endif /* !__PYX_HAVE__hello */
We changed line 203 in the hello.c file from:
enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
to
enum { __pyx_check_sizeof_voidp = (int)(SIZEOF_VOID_P == sizeof(void*)) };
To fix the error.
Afterwards we executed the following two commands to create the dll.
gcc -c -DBUILD_DLL hello.c -IC:/Users/hannah/Anaconda3/include
gcc -shared -o hello.dll hello.o -LC:/Users/hannah/Anaconda3/libs -lpyhton38
This successfully creates hello.dll. If I open this DLL with Dependency Walker I see that there are 2 methods available: Methods in dependency Walker
As we tried to call the functions via the DLL, the program stops at the initialization of the Python file. To call the functions we used the following code:
#ifndef DLLHANDLER_C_
#define DLLHANDLER_C_
#include <windows.h>
#include <winbase.h>
#include <windef.h>
#include <stdio.h>
typedef int (*pFunHello)();
typedef void (*pFunInit)(void);
int loadDLL();
int main(){
//int x = 100;
//int x = loadDLL();
loadDLL();
}
int loadDLL( ) {
int status = 10;
pFunHello _TestFunc;
pFunInit _Py_init;
HMODULE testLibrary = LoadLibrary("hello.dll");
if (testLibrary != NULL)
{
printf("Library successfully loaded.\n");
_Py_init = (pFunInit)GetProcAddress(testLibrary, "PyInit_hello");
if (_Py_init != NULL)
{
printf("PyInit_hello successfully cached.\n");
_Py_init();
printf("Python initialization successful.\n");
_TestFunc = (pFunHello)GetProcAddress(testLibrary, "Py_sayHello");
if (_TestFunc != NULL)
{
printf("Py_sayHello successfully cached.\n");
status = _TestFunc();
printf("Py_sayHello returned %d\n", status);
}
else
{
printf("Error when caching Py_sayHello: %d\n", GetLastError());
}
}
else
{
printf("Error when caching PyInit_hello: %d\n", GetLastError());
}
FreeLibrary(testLibrary);
}
else
{
printf("Error occurred when loading library: %d\n", GetLastError());
}
return status;
}
#endif
And the output was:
Library successfully loaded.
PyInit_hello successfully cached.
Calling PyModuleDef_Init...
In the command line through the command:
echo %Error Level%
the Error Code -1073741819 appeared, which means "Access violation error". My colleague was able to determine, that the error comes from the PyModuleDef_Init from python38.dll.
Hopefully some of you can help us to fix this problem. Does anybody have much experience with cython? How can we fix this error and make the hello.dll work properly?