1

Both the dll and the calling file are release versions

Operating system: win11 IDE:visual studio 2022 conda environment: python=3.6 cython=0.29.33 command to generate c file cython demo.pyx -3

demo.pyx

cdef public int add( int str1, int str2):
    return int(str1) + int(str2)

Generate dll files code

#include <Windows.h>
#include <Python.h>
#include "demo.h"

extern "C" _declspec(dllexport)  int  p_add(int a, int b);

int p_add(int a, int b)
{
    int p = add(a, b);
    return p;
}
    


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        Py_Initialize();
        PyInit_demo();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        Py_Finalize();
        break;
    }
    return TRUE;
}


Callback file code

#include <iostream>
#include <Windows.h>

typedef int(*fun)(int, int);

int main()
{   
    fun funName = NULL;
    HMODULE hMoudle =LoadLibraryA("D:\\stduioProject\\python_gen_dll\\x64\\Release\\python_gen_dll.dll");
    {
        FreeLibrary(hMoudle);
        std::cout << GetLastError();  // error code 1411
        return -1;
    }
    funName = (fun)GetProcAddress(hMoudle, "p_add");
    if (funName == NULL)
    {
        printf("error");
        FreeLibrary(hMoudle);
        return -10;
    }
    int f = funName(2, 3);
    std::cout << f << std::endl;
    FreeLibrary(hMoudle);
}

I'm expecting to return answer 5, but I don't know how to do it.

I lowered python3.8 to 3.6 for testing but still have the same problem

CristiFati
  • 38,250
  • 9
  • 50
  • 87
Xi Zhu
  • 11
  • 1
  • *demo.h* and compiler and linker flags? The error doesn't make any sense. Application and *.dll* project types? Also, it's ***\_\_declspec***. – CristiFati Feb 19 '23 at 14:32
  • You are calling `FreeLibrary` and printing the error without even checking whether `LoadLibraryA` succeeded or failed. In other words, the program always exits unconditionally after `LoadLibraryA`, and never gets to `GetProcAddress` and so on. Did you mean to have an `if` statement somewhere before the open brace? – Igor Tandetnik Feb 19 '23 at 15:22
  • Also take a look at https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices. – CristiFati Feb 19 '23 at 17:29
  • What is working? Code doesn't even compile, also the function is not exported from the module. – CristiFati Feb 20 '23 at 06:51
  • I'm very sorry, I made a low-level mistake, my if judgment was deleted when I was debugging before, so it caused this error – Xi Zhu Feb 20 '23 at 11:40

1 Answers1

0

There are many errors preventing this to work. Mentioning some (besides the actual function call - which is the question target):

I prepared a working example, using Python 3.6, with Cython 0.29.33 and VStudio 2022 (NMake) for build (from command line).

  • code00.pyx:

    def add(int n1, int n2):
        return n1 + n2
    
    
    # The following function is NOT exported by the extension module
    cdef public int add_orig( int str1, int str2):
        return int(str1) + int(str2)
    
  • dll00.c:

    #include <Windows.h>
    #include <Python.h>
    
    
    #if defined(__cplusplus)
    extern "C" {
    #endif
    
    __declspec(dllexport) int init();
    __declspec(dllexport) void cleanup();
    
    __declspec(dllexport) int p_add(int a, int b);
    
    #if defined(__cplusplus)
    }
    #endif
    
    
    void *gpDict = NULL;
    
    
    static void *loadFunc(const char *name)
    {
        if (gpDict == NULL) {
            printf("Error\n");
            return NULL;
        }
        return PyDict_GetItemString(gpDict, name);
    }
    
    
    int init()
    {
        Py_Initialize();
        void *pMod = PyImport_ImportModule("code00");
        if (pMod == NULL) {
            printf("Python engine error\n");
            return -1;
        }
        gpDict = PyModule_GetDict(pMod);
        if (gpDict == NULL) {
            printf("Python engine error\n");
            return -2;
        }
        return 0;
    }
    
    
    void cleanup()
    {
        gpDict = NULL;
        Py_Finalize();
    }
    
    
    int p_add(int a, int b)
    {
        PyObject *pFunc = loadFunc("add");
        if (pFunc == NULL) {
            return 0;
        }
        PyObject *pRet = PyObject_CallFunction(pFunc, "ii", a, b);
        int ret = (pRet == NULL) ? 0 : PyLong_AsLong(pRet);
        Py_XDECREF(pRet);
        return ret;
    }
    
    
    BOOL APIENTRY DllMain(HMODULE hModule,
                          DWORD  ul_reason_for_call,
                          LPVOID lpReserved)
    {
        switch (ul_reason_for_call) {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            cleanup();
            break;
        }
        return TRUE;
    }
    
  • app00.cpp:

    #include <iostream>
    #include <Windows.h>
    
    
    typedef int (*pInitPtr)();
    typedef void (*pCleanupPtr)();
    typedef int (*pAddPtr)(int, int);
    
    
    int main()
    {
        HMODULE hMoudle = LoadLibraryA("dll00.dll");
        if (hMoudle == NULL) {
            FreeLibrary(hMoudle);
            std::cout << "error: " << GetLastError();
            return -1;
        }
        pInitPtr pInit = (pInitPtr)GetProcAddress(hMoudle, "init");
        pCleanupPtr pCleanup = (pCleanupPtr)GetProcAddress(hMoudle, "cleanup");
        pAddPtr pAdd = (pAddPtr)GetProcAddress(hMoudle, "p_add");
        if ((pInit == NULL) || (pCleanup == NULL) || (pAdd == NULL)) {
            std::cout << "error\n";
            FreeLibrary(hMoudle);
            return -2;
        }
        int res = pInit();
        std::cout << "Init result: " << res << "\n";
        int f = pAdd(2, 3);
        std::cout << "Function result: " << f << std::endl;
        FreeLibrary(hMoudle);
        return 0;
    }
    
  • Makefile.mak (build - check [SO]: Visual Studio NMake build fails with: fatal error U1052: file 'win32.mak' not found (@CristiFati's answer)):

    NODEBUG=1
    !include <win32.mak>  # @TODO - cfati: Check URL
    
    CODE00=code00
    DLL00=dll00
    APP00=app00
    
    CODE00_PYD=$(CODE00).pyd
    DLL00_DLL=$(DLL00).dll
    APP00_EXE=$(APP00).exe
    
    
    all: $(CODE00_PYD) $(DLL00_DLL) $(APP00_EXE)
    
    clean:
        del /f /q *.exe *.dll *.pyd *.lib *.exp *.pdb *.obj $(CODE00).c $(CODE00).h
    
    
    .c.obj:
        $(CC) $(cdebug) $(cflags) $(cvarsdll) -I"$(HOME_PYTHON)\include" /c $<
    
    $(CODE00).c: $(CODE00).pyx
        "$(HOME_PYTHON)\Scripts\python.exe" -m Cython.Build.Cythonize -3 $?
    
    $(CODE00).pyd: $(CODE00).obj
        $(link) $(ldebug) $(dlllflags) $(conlibsdll) /LIBPATH:"$(HOME_PYTHON)\libs" /OUT:$@ $? python$(PY_MAJ)$(PY_MIN).lib
    
    $(DLL00_DLL): $(DLL00).obj
        $(link) $(ldebug) $(dlllflags) $(conlibsdll) /LIBPATH:"$(HOME_PYTHON)\libs" /OUT:$@ $? python$(PY_MAJ)$(PY_MIN).lib
    
    $(APP00_EXE): $(APP00).obj
        $(link) $(ldebug) $(conlflags) $(conlibsdll) /OUT:$@ $(APP00).obj
    
    $(APP00).obj: $(APP00).cpp
        $(CPP) $(cdebug) $(cflags) $(cvarsdll) -U_DLL -EHsc -Fo$@ $?
    

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q075500716]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[prompt]> "c:\Install\pc064\Microsoft\VisualStudioCommunity\2022\VC\Auxiliary\Build\vcvarsall.bat" x64 > nul

[prompt]>
[prompt]> dir /b
app00.cpp
code00.pyx
dll00.c
Makefile.mak

[prompt]>
[prompt]> :: Backup
[prompt]> set _INCLUDE=%INCLUDE%

[prompt]> set _PATH=%PATH%

[prompt]>
[prompt]> :: Python stuff
[prompt]> set PY_MAJ=3

[prompt]> set PY_MIN=6

[prompt]> set HOME_PYTHON=e:\Work\Dev\VEnvs\py_pc064_0%PY_MAJ%.0%PY_MIN%_test0

[prompt]>
[prompt]> :: Required by NMake
[prompt]> set INCLUDE=%_INCLUDE%;e:\Work\Dev\GitHub\CristiFati\MSSDKFiles\src\Include

[prompt]>
[prompt]> nmake /f Makefile.mak

Microsoft (R) Program Maintenance Utility Version 14.34.31942.0
Copyright (C) Microsoft Corporation.  All rights reserved.

        "e:\Work\Dev\VEnvs\py_pc064_03.06_test0\Scripts\python.exe" -m Cython.Build.Cythonize -3 code00.pyx
Compiling e:\Work\Dev\StackOverflow\q075500716\code00.pyx because it changed.
[1/1] Cythonizing e:\Work\Dev\StackOverflow\q075500716\code00.pyx
        cl -Ox -DNDEBUG -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MD -I"e:\Work\Dev\VEnvs\py_pc064_03.06_test0\include" /c code00.c
code00.c
e:\Work\Dev\VEnvs\py_pc064_03.06_test0\include\pytime.h(122): warning C4115: 'timeval': named type definition in parentheses
code00.c(1337): warning C4100: '__pyx_self': unreferenced formal parameter
code00.c(1659): warning C4100: 'def': unreferenced formal parameter
code00.c(2014): warning C4127: conditional expression is constant
code00.c(2005): warning C4189: 'flags': local variable is initialized but not referenced
code00.c(2247): warning C4100: 'filename': unreferenced formal parameter
code00.c(2247): warning C4100: 'lineno': unreferenced formal parameter
code00.c(2246): warning C4100: 'clineno': unreferenced formal parameter
code00.c(2606): warning C4127: conditional expression is constant
code00.c(2608): warning C4127: conditional expression is constant
code00.c(2609): warning C4127: conditional expression is constant
code00.c(2610): warning C4127: conditional expression is constant
code00.c(2611): warning C4127: conditional expression is constant
code00.c(2617): warning C4127: conditional expression is constant
code00.c(2618): warning C4127: conditional expression is constant
code00.c(2619): warning C4127: conditional expression is constant
code00.c(2620): warning C4127: conditional expression is constant
code00.c(2626): warning C4127: conditional expression is constant
code00.c(2627): warning C4127: conditional expression is constant
code00.c(2628): warning C4127: conditional expression is constant
code00.c(2629): warning C4127: conditional expression is constant
code00.c(2649): warning C4127: conditional expression is constant
code00.c(2650): warning C4127: conditional expression is constant
code00.c(2652): warning C4127: conditional expression is constant
code00.c(2653): warning C4127: conditional expression is constant
code00.c(2661): warning C4127: conditional expression is constant
code00.c(2662): warning C4127: conditional expression is constant
code00.c(2664): warning C4127: conditional expression is constant
code00.c(2665): warning C4127: conditional expression is constant
code00.c(2666): warning C4127: conditional expression is constant
code00.c(2667): warning C4127: conditional expression is constant
code00.c(2673): warning C4127: conditional expression is constant
code00.c(2674): warning C4127: conditional expression is constant
code00.c(2675): warning C4127: conditional expression is constant
code00.c(2676): warning C4127: conditional expression is constant
code00.c(2682): warning C4127: conditional expression is constant
code00.c(2683): warning C4127: conditional expression is constant
code00.c(2684): warning C4127: conditional expression is constant
code00.c(2685): warning C4127: conditional expression is constant
code00.c(2691): warning C4127: conditional expression is constant
code00.c(2692): warning C4127: conditional expression is constant
code00.c(2693): warning C4127: conditional expression is constant
code00.c(2694): warning C4127: conditional expression is constant
code00.c(2700): warning C4127: conditional expression is constant
code00.c(2701): warning C4127: conditional expression is constant
code00.c(2702): warning C4127: conditional expression is constant
code00.c(2703): warning C4127: conditional expression is constant
code00.c(2709): warning C4127: conditional expression is constant
code00.c(2710): warning C4127: conditional expression is constant
code00.c(2711): warning C4127: conditional expression is constant
code00.c(2712): warning C4127: conditional expression is constant
code00.c(2719): warning C4127: conditional expression is constant
code00.c(2720): warning C4127: conditional expression is constant
code00.c(2722): warning C4127: conditional expression is constant
code00.c(2723): warning C4127: conditional expression is constant
code00.c(2784): warning C4127: conditional expression is constant
code00.c(2786): warning C4127: conditional expression is constant
code00.c(2789): warning C4127: conditional expression is constant
code00.c(2794): warning C4127: conditional expression is constant
code00.c(2797): warning C4127: conditional expression is constant
code00.c(2822): warning C4127: conditional expression is constant
code00.c(2824): warning C4127: conditional expression is constant
code00.c(2827): warning C4127: conditional expression is constant
code00.c(2832): warning C4127: conditional expression is constant
code00.c(2835): warning C4127: conditional expression is constant
code00.c(2878): warning C4127: conditional expression is constant
code00.c(2880): warning C4127: conditional expression is constant
code00.c(2881): warning C4127: conditional expression is constant
code00.c(2882): warning C4127: conditional expression is constant
code00.c(2883): warning C4127: conditional expression is constant
code00.c(2889): warning C4127: conditional expression is constant
code00.c(2890): warning C4127: conditional expression is constant
code00.c(2891): warning C4127: conditional expression is constant
code00.c(2892): warning C4127: conditional expression is constant
code00.c(2898): warning C4127: conditional expression is constant
code00.c(2899): warning C4127: conditional expression is constant
code00.c(2900): warning C4127: conditional expression is constant
code00.c(2901): warning C4127: conditional expression is constant
code00.c(2921): warning C4127: conditional expression is constant
code00.c(2922): warning C4127: conditional expression is constant
code00.c(2924): warning C4127: conditional expression is constant
code00.c(2925): warning C4127: conditional expression is constant
code00.c(2933): warning C4127: conditional expression is constant
code00.c(2934): warning C4127: conditional expression is constant
code00.c(2936): warning C4127: conditional expression is constant
code00.c(2937): warning C4127: conditional expression is constant
code00.c(2938): warning C4127: conditional expression is constant
code00.c(2939): warning C4127: conditional expression is constant
code00.c(2945): warning C4127: conditional expression is constant
code00.c(2946): warning C4127: conditional expression is constant
code00.c(2947): warning C4127: conditional expression is constant
code00.c(2948): warning C4127: conditional expression is constant
code00.c(2954): warning C4127: conditional expression is constant
code00.c(2955): warning C4127: conditional expression is constant
code00.c(2956): warning C4127: conditional expression is constant
code00.c(2957): warning C4127: conditional expression is constant
code00.c(2963): warning C4127: conditional expression is constant
code00.c(2964): warning C4127: conditional expression is constant
code00.c(2965): warning C4127: conditional expression is constant
code00.c(2966): warning C4127: conditional expression is constant
code00.c(2972): warning C4127: conditional expression is constant
code00.c(2973): warning C4127: conditional expression is constant
code00.c(2974): warning C4127: conditional expression is constant
code00.c(2975): warning C4127: conditional expression is constant
code00.c(2981): warning C4127: conditional expression is constant
code00.c(2982): warning C4127: conditional expression is constant
code00.c(2983): warning C4127: conditional expression is constant
code00.c(2984): warning C4127: conditional expression is constant
code00.c(2991): warning C4127: conditional expression is constant
code00.c(2992): warning C4127: conditional expression is constant
code00.c(2994): warning C4127: conditional expression is constant
code00.c(2995): warning C4127: conditional expression is constant
code00.c(3390): warning C4127: conditional expression is constant
code00.c(3395): warning C4127: conditional expression is constant
code00.c(3400): warning C4127: conditional expression is constant
code00.c(3405): warning C4127: conditional expression is constant
code00.c(3410): warning C4127: conditional expression is constant
code00.c(3415): warning C4127: conditional expression is constant
code00.c(3431): warning C4127: conditional expression is constant
        link /RELEASE  /INCREMENTAL:NO /NOLOGO -entry:_DllMainCRTStartup -dll kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /LIBPATH:"e:\Work\Dev\VEnvs\py_pc064_03.06_test0\libs" /OUT:code00.pyd code00.obj python36.lib
   Creating library code00.lib and object code00.exp
        cl -Ox -DNDEBUG -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MD -I"e:\Work\Dev\VEnvs\py_pc064_03.06_test0\include" /c dll00.c
dll00.c
dll00.c(71): warning C4100: 'lpReserved': unreferenced formal parameter
dll00.c(69): warning C4100: 'hModule': unreferenced formal parameter
        link /RELEASE  /INCREMENTAL:NO /NOLOGO -entry:_DllMainCRTStartup -dll kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /LIBPATH:"e:\Work\Dev\VEnvs\py_pc064_03.06_test0\libs" /OUT:dll00.dll dll00.obj python36.lib
   Creating library dll00.lib and object dll00.exp
        cl -Ox -DNDEBUG -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MD -U_DLL -EHsc -Foapp00.obj app00.cpp
cl : Command line warning D9025 : overriding '/D_DLL' with '/U_DLL'
app00.cpp
        link /RELEASE  /INCREMENTAL:NO /NOLOGO -subsystem:console,6.0 kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /OUT:app00.exe app00.obj

[prompt]>
[prompt]> dir /b
app00.cpp
app00.exe
app00.obj
code00.c
code00.exp
code00.h
code00.lib
code00.obj
code00.pyd
code00.pyx
dll00.c
dll00.dll
dll00.exp
dll00.lib
dll00.obj
Makefile.mak

[prompt]>
[prompt]> :: Add Python to PATH
[prompt]> set PATH=%_PATH%;%HOME_PYTHON%\Scripts

[prompt]>
[prompt]> app00.exe
Init result: 0
Function result: 5

[prompt]>
[prompt]> :: Module export functions
[prompt]> "%HOME_PYTHON%\Scripts\python.exe" -c "import code00;print(code00);print(dir(code00));print(\"\nDone.\n\")"
<module 'code00' from 'e:\\Work\\Dev\\StackOverflow\\q075500716\\code00.pyd'>
['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__test__', 'add']

Done.
CristiFati
  • 38,250
  • 9
  • 50
  • 87