How can I use a DLL file from Python?
For ease of use, ctypes is the way to go.
The following example of ctypes is from actual code I've written (in Python 2.5). This has been, by far, the easiest way I've found for doing what you ask.
import ctypes
# Load DLL into memory.
hllDll = ctypes.WinDLL ("c:\\PComm\\ehlapi32.dll")
# Set up prototype and parameters for the desired function call.
# HLLAPI
hllApiProto = ctypes.WINFUNCTYPE (
ctypes.c_int, # Return type.
ctypes.c_void_p, # Parameters 1 ...
ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p) # ... thru 4.
hllApiParams = (1, "p1", 0), (1, "p2", 0), (1, "p3",0), (1, "p4",0),
# Actually map the call ("HLLAPI(...)") to a Python name.
hllApi = hllApiProto (("HLLAPI", hllDll), hllApiParams)
# This is how you can actually call the DLL function.
# Set up the variables and call the Python name with them.
p1 = ctypes.c_int (1)
p2 = ctypes.c_char_p (sessionVar)
p3 = ctypes.c_int (1)
p4 = ctypes.c_int (0)
hllApi (ctypes.byref (p1), p2, ctypes.byref (p3), ctypes.byref (p4))
The ctypes
stuff has all the C-type data types (int
, char
, short
, void*
, and so on) and can pass by value or reference. It can also return specific data types although my example doesn't do that (the HLL API returns values by modifying a variable passed by reference).
In terms of the specific example shown above, IBM's EHLLAPI is a fairly consistent interface.
All calls pass four void pointers (EHLLAPI sends the return code back through the fourth parameter, a pointer to an int
so, while I specify int
as the return type, I can safely ignore it) as per IBM's documentation here. In other words, the C variant of the function would be:
int hllApi (void *p1, void *p2, void *p3, void *p4)
This makes for a single, simple ctypes
function able to do anything the EHLLAPI library provides, but it's likely that other libraries will need a separate ctypes
function set up per library function.
The return value from WINFUNCTYPE
is a function prototype but you still have to set up more parameter information (over and above the types). Each tuple in hllApiParams
has a parameter "direction" (1 = input, 2 = output and so on), a parameter name and a default value - see the ctypes
doco for details
Once you have the prototype and parameter information, you can create a Python "callable" hllApi
with which to call the function. You simply create the needed variable (p1
through p4
in my case) and call the function with them.
Python import dll
You've tagged the question ctypes and so it sounds like you already know the answer.
The ctypes tutorial is excellent. Once you've read and understood that you'll be able to do it easily.
For example:
>>> from ctypes import *
>>> windll.kernel32.GetModuleHandleW(0)
486539264
And an example from my own code:
lib = ctypes.WinDLL('mylibrary.dll')
#lib = ctypes.WinDLL('full/path/to/mylibrary.dll')
func = lib['myFunc']#my func is double myFunc(double);
func.restype = ctypes.c_double
value = func(ctypes.c_double(42.0))
Loading dll using Python Ctypes
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;
}
Accessing DLL function using ctypes
You're on the right track but got a bit confused along the way - taking a code file and giving it a .dll
extension isn't enough to turn it into a DLL, you do still need to compile it. Your linker is telling you that it doesn't know how to parse your file:
myfunctionsDLL2.dll : warning LNK4048: Invalid format file; ignored
because it only knows how to parse real executables.
You should rename your second code file (the one you named my_functionsDLL2.dll
) back to my_functions.c
- and compile it the same way you did the first time. But this time, because you added __declspec(dllexport)
to your function definition, your compiler (cl.exe
) will know that these functions are meant to be exported from the DLL and will export them, making them available through ctypes.
How use correctly a .dll file in python on linux and mac
As hoefling explained, *.dll libraries are only for Windows.
At the site you've specified, there already are libraries built for and Linux.
The static lib propa64.a
definitely should work on Linux, and I guess if it's for x86
64-bit
platform, it should also work on MacOS.
Related Topics
Importerror: No Module Named Requests
What Is the Purpose of the -M Switch
Pandas: Filter Rows of Dataframe with Operator Chaining
Pygame.Event.Get() Not Returning Any Events When Inside a Thread
How to .Decode('String-Escape') in Python 3
Understanding Nested List Comprehension
How to Speed Up Bulk Insert to Ms SQL Server Using Pyodbc
How to Get the Named Parameters from a Url Using Flask
Removing Item from List - During Iteration - What's Wrong with This Idiom
How to Use Python to Login to a Webpage and Retrieve Cookies for Later Usage
Shared-Memory Objects in Multiprocessing
How to Convert SQLalchemy Row Object to a Python Dict
Python Socket Not Receiving Without Sending
Prepend Line to Beginning of a File
Python Nameerror: Name Is Not Defined