Loading dll using Python Ctypes
Question:
I’ve looked at the example given here ctypes – Beginner and followed the same steps with a different bit of C code. I’ve built a .dll and a .lib using C code given here: http://wolfprojects.altervista.org/articles/dll-in-c-for-python/
//test.c
__declspec(dllexport) int sum(int a, int b) {
return a + b;
}
In my wrapper.py I have this:
import ctypes
testlib = ctypes.CDLL("C:\Users\xyz\Documents\Python\test.dll")
When I run the script I get this error:
self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 is not a valid Win32 application
If I use
testlib = ctypes.LibraryLoader("C:\Users\xyz\Documents\Python\test.dll")
then I don’t get any error on running the script. But If I try to do this:
testlib.sum(3,4)
I get the error:
dll = self._dlltype(name)
TypeError: ‘str’ object is not callable
The dll and the .py are in the same folder. Can anyone help me understand what’s going on here. I’ve spent hours trying to figure this out, but have hit a wall. Thanks.
Answers:
After further digging I’ve found out the solution. The C compiler has mangled the name of the function which is why I got an Attribute error when calling the sum method. I had to use link.exe to figure out the mangled name and then used the getattr method.
More details and explanation in this post:
Python: accessing DLL function using ctypes — access by function *name* fails
Make sure your compiler and version of Python are both 32-bit or both 64-bit. You can’t mix, which is the cause of OSError: [WinError 193] %1 is not a valid Win32 application
.
Next, make sure to compile as a C program and not C++. That’s the cause of the name mangling mention in your answer.
Example (note compiler is for x86 not x64:
C:>cl /LD /W4 test.c
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
test.c
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:test.dll
/dll
/implib:test.lib
test.obj
Creating library test.lib and object test.exp
Now use a 32-bit Python:
C:>py -2
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> lib = CDLL('test')
>>> lib.sum(2, 3)
5
If you compile as C++, you can still call functions by exporting them as C, which prevents the C++ name mangling:
test.cpp
extern "C" __declspec(dllexport) int sum(int a, int b) {
return a + b;
}
I’ve looked at the example given here ctypes – Beginner and followed the same steps with a different bit of C code. I’ve built a .dll and a .lib using C code given here: http://wolfprojects.altervista.org/articles/dll-in-c-for-python/
//test.c
__declspec(dllexport) int sum(int a, int b) {
return a + b;
}
In my wrapper.py I have this:
import ctypes
testlib = ctypes.CDLL("C:\Users\xyz\Documents\Python\test.dll")
When I run the script I get this error:
self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 is not a valid Win32 application
If I use
testlib = ctypes.LibraryLoader("C:\Users\xyz\Documents\Python\test.dll")
then I don’t get any error on running the script. But If I try to do this:
testlib.sum(3,4)
I get the error:
dll = self._dlltype(name)
TypeError: ‘str’ object is not callable
The dll and the .py are in the same folder. Can anyone help me understand what’s going on here. I’ve spent hours trying to figure this out, but have hit a wall. Thanks.
After further digging I’ve found out the solution. The C compiler has mangled the name of the function which is why I got an Attribute error when calling the sum method. I had to use link.exe to figure out the mangled name and then used the getattr method.
More details and explanation in this post:
Python: accessing DLL function using ctypes — access by function *name* fails
Make sure your compiler and version of Python are both 32-bit or both 64-bit. You can’t mix, which is the cause of OSError: [WinError 193] %1 is not a valid Win32 application
.
Next, make sure to compile as a C program and not C++. That’s the cause of the name mangling mention in your answer.
Example (note compiler is for x86 not x64:
C:>cl /LD /W4 test.c
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
test.c
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:test.dll
/dll
/implib:test.lib
test.obj
Creating library test.lib and object test.exp
Now use a 32-bit Python:
C:>py -2
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> lib = CDLL('test')
>>> lib.sum(2, 3)
5
If you compile as C++, you can still call functions by exporting them as C, which prevents the C++ name mangling:
test.cpp
extern "C" __declspec(dllexport) int sum(int a, int b) {
return a + b;
}