0

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?

Cori
  • 39
  • 4
  • Is it possible to reopen this question? I looked at this [example](https://stackoverflow.com/questions/18515275/can-cython-code-be-compiled-to-a-dll-so-c-application-can-call-it) but it doesn't solve my problem. Or am I missing something in that post? I would appreciate a clarification. I already changed the details in my question. – Cori Jun 24 '21 at 10:22
  • There's no indication that you've initialized the Python interpreter (i.e. no `Py_Initialize`) so it doesn't look to me like you've actually followed the linked example – DavidW Jun 24 '21 at 16:37
  • Also 1) `__Pyx_PyInt_As_int` converts a Python integer to a C integer, but `sayHello` already returns a C integer so your wrapper function is nonsense (and should be giving you serious compiler warnings). 2) You haven't "fixed" `__pyx_check_sizeof_voidp` - you'd disabled a useful check that was telling you that your compiler would not be compatible (likely because you are using Mingw, see https://github.com/cython/cython/issues/2670) – DavidW Jun 24 '21 at 21:50

0 Answers0