0

Good day!

I'm trying to make my little test dll to work in python code, using ctypes.

Here is my cppmul.cpp:

#include <iostream>

using namespace std;

extern "C" __declspec(dllexport) float cmul(int int_param, float float_param) {
    float return_value = int_param * float_param;
    std::cout << "In cmult: int: " << int_param << ", float: " << float_param << ", returning: " << return_value << std::endl;
    return return_value;
}

extern "C" __declspec(dllexport) void hello() {
    std::cout << "wheee" << std::endl;
    return;
}

Which I build with the next script:

g++ -c cppmul.cpp
g++ -shared -o libcppmul.dll -Wl,-out-implib,libcppmul.a -Wl,--export-all-symbols -Wl,--enable-auto-image-base cppmul.o

Then in the python script I just load dll and trying to call function:

# loads great
lib = ctypes.WinDLL(libname, winmode=1)
lib.hello.restype = None
# exception here
lib.hello()

And get: OSError: exception: access violation writing 0x0000000000009658

OS Windows 10 x64, Python 3.9 x64.

Any suggestions?

I think maybe the problem is a some kind of type mismatch? But there are no types in the hello() function, only a void as return and an empty argument list.

  • 1
    Looking up the documentation for the flag value you're passing for `winmode`, I see a big "Do not use this value; it is provided only for backward compatibility.", and documentation about how it's designed to provide behavior that doesn't seem to fit your use case. Why did you pass `winmode=1` in the first place? – user2357112 Feb 23 '23 at 13:48
  • @user2357112, thank you a lot for your answer. I use `winmode=1` because in other case I get another exception when trying to load my dll with `ctypes.WinDLL`: FileNotFoundError: Could not find module. Do you think I must to search another solution for this trouble? I will try. – Julia Esina Feb 23 '23 at 13:57

1 Answers1

0

I reproduced the crash with winmode=1 and MSVC compiler. Removing winmode=1 and using a relative path ('./cppmul') works correctly.

Note that CDLL is the correct function to use with default __cdecl calling convention. WinDLL is for __stdcall calling convention, but both will work 64-bit builds. It will only matter for 32-bit compatibility.

Here's a complete example calling both functions:

import ctypes as ct

lib = ct.CDLL('./cppmul')
lib.hello.argtypes = ()
lib.hello.restype = None
lib.cmul.argtypes = ct.c_int, ct.c_float
lib.cmul.restype = ct.c_float
lib.hello()
print(lib.cmul(2, 3.4))

Output:

wheee
In cmult: int: 2, float: 3.4, returning: 6.8
6.800000190734863
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251