I have written some functions within my C++ app and i compiled it to use it as .dll
and so i can use those functions in python for a better performance. The .dll
file works fine when i'm using it for another C++ application but when i want to load it in my python program it throws this error:
Traceback (most recent call last):
File "e:\My Apps\Python\Telegram_Bots\Calculator\main.py", line 6, in <module>
lib = CDLL("E:\My Apps\Python\Telegram_Bots\Calculator\lib.dll")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\KHATAM_PC\AppData\Local\Programs\Python\Python311\Lib\ctypes\__init__.py", line 376, in __init__
self._handle = _dlopen(self._name, mode)
^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: Could not find module 'E:\My Apps\Python\Telegram_Bots\Calculator\lib.dll' (or one of its dependencies). Try using the full path with constructor syntax.
I've quarterable checked the path and even used the full-path, never worked, been trying for a whole day, compiling the .dll
again and again in different ways and methods but nothing came out of them, all of them yet worked in C++
.dll
exportation command: g++ -DMATH_DLL_EXPORTS -shared -std=c++17 -o lib.dll lib.cpp
lib.hpp
:
// #pragma once
#ifndef MATH_DLL_API
#define MATH_DLL_API
#ifdef _WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
#include <iostream>
#include <vector>
extern "C" {
DLL_EXPORT int precedence(char o);
DLL_EXPORT float calc(float a, float b, char o);
DLL_EXPORT void calculate(std::vector<float>& values, std::vector<char>& ops);
DLL_EXPORT float evaluate(std::string e);
}
#endif // MATH_DLL_API
lib.cpp
:
#include "lib.hpp"
#include <iostream>
#include <vector>
extern "C" {
DLL_EXPORT int precedence(char o) { ... }
DLL_EXPORT float calc(float a, float b, char o) { ... }
DLL_EXPORT void calculate(std::vector<float>& values, std::vector<char>& ops) { ... }
DLL_EXPORT float evaluate(std::string e) { ... }
}
And finaly, the python script:
from ctypes import c_char, c_int, c_float, c_char_p, c_void_p, CDLL, cdll, POINTER
lib = CDLL("E:\My Apps\Python\Telegram_Bots\Calculator\lib.dll")
lib.evaluate.argtypes = [c_char_p]
lib.evaluate.restype = c_float
lib.calculate.argtypes = [POINTER(c_float), POINTER(c_char)]
lib.calculate.restype = c_void_p
lib.calc.argtypes = [c_float, c_float, c_char]
lib.calc.restype = c_float
lib.precedence.argtypes = [c_char]
lib.precedence.restype = c_int
Can anybody help please?
I have written some functions within my C++ app and i compiled it to use it as .dll
and so i can use those functions in python for a better performance. The .dll
file works fine when i'm using it for another C++ application but when i want to load it in my python program it throws this error:
Traceback (most recent call last):
File "e:\My Apps\Python\Telegram_Bots\Calculator\main.py", line 6, in <module>
lib = CDLL("E:\My Apps\Python\Telegram_Bots\Calculator\lib.dll")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\KHATAM_PC\AppData\Local\Programs\Python\Python311\Lib\ctypes\__init__.py", line 376, in __init__
self._handle = _dlopen(self._name, mode)
^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: Could not find module 'E:\My Apps\Python\Telegram_Bots\Calculator\lib.dll' (or one of its dependencies). Try using the full path with constructor syntax.
I've quarterable checked the path and even used the full-path, never worked, been trying for a whole day, compiling the .dll
again and again in different ways and methods but nothing came out of them, all of them yet worked in C++
.dll
exportation command: g++ -DMATH_DLL_EXPORTS -shared -std=c++17 -o lib.dll lib.cpp
lib.hpp
:
// #pragma once
#ifndef MATH_DLL_API
#define MATH_DLL_API
#ifdef _WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
#include <iostream>
#include <vector>
extern "C" {
DLL_EXPORT int precedence(char o);
DLL_EXPORT float calc(float a, float b, char o);
DLL_EXPORT void calculate(std::vector<float>& values, std::vector<char>& ops);
DLL_EXPORT float evaluate(std::string e);
}
#endif // MATH_DLL_API
lib.cpp
:
#include "lib.hpp"
#include <iostream>
#include <vector>
extern "C" {
DLL_EXPORT int precedence(char o) { ... }
DLL_EXPORT float calc(float a, float b, char o) { ... }
DLL_EXPORT void calculate(std::vector<float>& values, std::vector<char>& ops) { ... }
DLL_EXPORT float evaluate(std::string e) { ... }
}
And finaly, the python script:
from ctypes import c_char, c_int, c_float, c_char_p, c_void_p, CDLL, cdll, POINTER
lib = CDLL("E:\My Apps\Python\Telegram_Bots\Calculator\lib.dll")
lib.evaluate.argtypes = [c_char_p]
lib.evaluate.restype = c_float
lib.calculate.argtypes = [POINTER(c_float), POINTER(c_char)]
lib.calculate.restype = c_void_p
lib.calc.argtypes = [c_float, c_float, c_char]
lib.calc.restype = c_float
lib.precedence.argtypes = [c_char]
lib.precedence.restype = c_int
Can anybody help please?
Share Improve this question asked Mar 13 at 11:25 user26649650user26649650 55 bronze badges 10 | Show 5 more comments1 Answer
Reset to default 0As the error text indicates, your library (or one of its dependent .dlls) is not found. For more details on .dll dependencies, check [SO]: Discover missing module using command-line ("DLL load failed" error) (@CristiFati's answer)
- Once dependencies were identified, their locations must be added to the .dll search paths. Check [SO]: PyWin32 and Python 3.8.0 (@CristiFati's answer) for more details
[Python.Docs]: ctypes - A foreign function library for Python (as its name suggests), works with C not C++, therefore any STL stuff should be wrapped in C functions. Might also want to check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) for a common pitfall when working with CTypes (calling functions)
I prepared a MCVE. Based on your build command, I assume you're using a Nix emulator - I am using MSYS2.
dll00.hpp:
#pragma once #include <string> #include <vector> #include <cstdint> #if defined(_WIN32) # if defined(DLL00_EXPORTS) # define DLL00_EXPORT_API __declspec(dllexport) # else # define DLL00_EXPORT_API __declspec(dllimport) # endif #else # define DLL00_EXPORT_API #endif DLL00_EXPORT_API void calculate(std::vector<float> &values, std::vector<char> &ops); DLL00_EXPORT_API float evaluate(std::string s); #if defined(__cplusplus) extern "C" { #endif DLL00_EXPORT_API int precedence(char c); DLL00_EXPORT_API float calc(float f0, float f1, char c); DLL00_EXPORT_API void calculate_c(float *values, size_t v_size, char *ops, size_t o_size); DLL00_EXPORT_API float evaluate_c(const char *s); #if defined(__cplusplus) } #endif
dll00.cpp:
#define DLL00_EXPORTS #include "dll00.hpp" #include <cstdio> int precedence(char c) { return c; } float calc(float f0, float f1, char c) { return f0 + f1 + c; } void calculate(std::vector<float> &values, std::vector<char> &ops) { for (size_t i = 0; i < values.size(); ++i) values[i] += ops[i % ops.size()]; } float evaluate(std::string s) { return s.size() / 2; } void calculate_c(float *values, size_t v_size, char *ops, size_t o_size) { std::vector<float> vs; vs.reserve(v_size); for (size_t i = 0; i < v_size; ++i) vs.emplace_back(values[i]); std::vector<char> os; os.reserve(o_size); for (size_t i = 0; i < o_size; ++i) os.emplace_back(ops[i]); calculate(vs, os); for (size_t i = 0; i < v_size; ++i) values[i] = vs[i]; } float evaluate_c(const char *s) { return evaluate(s); }
code00.py:
#!/usr/bin/env python import ctypes as cts import os import sys DLL_NAME = "./libdll00_msys.{:s}".format("dll" if sys.platform[:3].lower() == "win" else "so") FloatPtr = cts.POINTER(cts.c_float) CharPtr = cts.POINTER(cts.c_char) def main(*argv): if argv: add = getattr(os, "add_dll_directory") if add: print("Add directory") add(argv[0]) dll = cts.CDLL(DLL_NAME) precedence = dll.precedence precedence.argtypes = (cts.c_char,) precedence.restype = cts.c_int calc = dll.calc calc.argtypes = (cts.c_float, cts.c_float, cts.c_char) calc.restype = cts.c_float calculate = dll.calculate_c calculate.argtypes = (FloatPtr, cts.c_size_t, CharPtr, cts.c_size_t) calculate.restype = None evaluate = dll.evaluate_c evaluate.argtypes = (cts.c_char_p,) evaluate.restype = cts.c_float c = ord('A') print(f"\nprecedence: {precedence(c)}") print(f"\ncalc: {calc(0.9, -0.2, c)}") dim = 10 vs = tuple(1 / i for i in range(1, dim + 1)) cs = tuple(range(dim)) print(f"\ncalculate\nops: {cs}\nvalues (initial): {vs}") v_arr = (cts.c_float * dim)(*vs) # Create CTypes arrays from Python sequences c_arr = (cts.c_char * dim)(*cs) values = cts.cast(v_arr, FloatPtr) # Cast arrays to pointers ops = cts.cast(c_arr, CharPtr) calculate(values, dim, ops, dim) print(f"values (final): {[values[i] for i in range(dim)]}") print(f"\nevaluate: {evaluate(b'20 chars long string')}") if __name__ == "__main__": print( "Python {:s} {:03d}bit on {:s}\n".format( " ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform, ) ) rc = main(*sys.argv[1:]) print("\nDone.\n") sys.exit(rc)
Output:
MSYS2 terminal:
[cfati@cfati-5510-0:/e/Work/Dev/StackExchange/StackOverflow/q079506302]> ~/sopr.sh ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ### [064bit prompt]> [064bit prompt]> ls code00.py dll00.cpp dll00.hpp [064bit prompt]> [064bit prompt]> g++ -fPIC -shared -std=c++17 -o libdll00_msys.dll dll00.cpp [064bit prompt]> [064bit prompt]> ls code00.py dll00.cpp dll00.hpp libdll00_msys.dll [064bit prompt]> [064bit prompt]> ldd ./libdll00_msys.dll ntdll.dll => /c/WINDOWS/SYSTEM32/ntdll.dll (0x7fff137f0000) KERNEL32.DLL => /c/WINDOWS/System32/KERNEL32.DLL (0x7fff136c0000) KERNELBASE.dll => /c/WINDOWS/System32/KERNELBASE.dll (0x7fff11030000) msvcrt.dll => /c/WINDOWS/System32/msvcrt.dll (0x7fff12280000) msys-2.0.dll => /usr/bin/msys-2.0.dll (0x180040000) msys-gcc_s-seh-1.dll => /usr/bin/msys-gcc_s-seh-1.dll (0x5e8160000) msys-stdc++-6.dll => /usr/bin/msys-stdc++-6.dll (0x526840000) advapi32.dll => /c/WINDOWS/System32/advapi32.dll (0x7fff12930000) sechost.dll => /c/WINDOWS/System32/sechost.dll (0x7fff12170000) RPCRT4.dll => /c/WINDOWS/System32/RPCRT4.dll (0x7fff12660000) bcrypt.dll => /c/WINDOWS/System32/bcrypt.dll (0x7fff116c0000) CRYPTBASE.DLL => /c/WINDOWS/SYSTEM32/CRYPTBASE.DLL (0x7fff10750000) bcryptPrimitives.dll => /c/WINDOWS/System32/bcryptPrimitives.dll (0x7fff10f30000)
As seen, the .dll depends on some MSYS2 .sos, which are not typically in (Win system) %PATH%, so they won't be available (from Cmd).
Cmd terminal:
[cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q079506302]> sopr.bat ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ### [prompt]> [prompt]> dir /b code00.py dll00.cpp dll00.hpp [prompt]> [prompt]> :: --- Build the .dll from a MSYS2 terminal --- [prompt]> [prompt]> dir /b code00.py dll00.cpp dll00.hpp libdll00_msys.dll [prompt]> [prompt]> :: Run normally [prompt]> python ./code00.py Python 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)] 064bit on win32 Traceback (most recent call last): File "e:\Work\Dev\StackExchange\StackOverflow\q079506302\code00.py", line 65, in <module> rc = main(*sys.argv[1:]) File "e:\Work\Dev\StackExchange\StackOverflow\q079506302\code00.py", line 20, in main dll = cts.CDLL(DLL_NAME) File "c:\Install\pc064\Python\Python\03.10\lib\ctypes\__init__.py", line 374, in __init__ self._handle = _dlopen(self._name, mode) FileNotFoundError: Could not find module 'e:\Work\Dev\StackExchange\StackOverflow\q079506302\libdll00_msys.dll' (or one of its dependencies). Try using the full path with constructor syntax. [prompt]> [prompt]> :: Pass the MSYS2 .dlls path [prompt]> python ./code00.py f:\Install\pc064\MSYS2\MSYS2\Version\usr\bin Python 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)] 064bit on win32 Add directory precedence: 65 calc: 65.69999694824219 calculate ops: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) values (initial): (1.0, 0.5, 0.3333333333333333, 0.25, 0.2, 0.16666666666666666, 0.14285714285714285, 0.125, 0.1111111111111111, 0.1) values (final): [1.0, 1.5, 2.3333332538604736, 3.25, 4.199999809265137, 5.166666507720947, 6.142857074737549, 7.125, 8.11111068725586, 9.100000381469727] evaluate: 10.0 Done.
depends.exe
but it hanged and crashed while trying to find dependencies to my dll – user26649650 Commented Mar 13 at 12:54