Calling C++ from python - python

I'm trying to call C++ from Python.
import ctypes
clibrary = ctypes.WinDLL("C:/Users/Desktop/SOURCE/build/libmy_library.dll")
my_library.hello_world()
I am most certainly sure that my_library.dll path is exactly correct. But I still get this error:
self._handle = _dlopen(self._name, mode)
FileNotFoundError: Could not find module 'C:\Users\Desktop\SOURCE\build\libmy_library.dll' (or one of its dependencies). Try using the full path with constructor syntax.
What is wrong here?
Note: If it matters my cmake is "Unix Makefiles". And I don't use visual studio, I use VS code.
Edit: Dependency Walker
Error: At least one required implicit or forwarded dependency was not found. Error: At least one module has an unresolved import due to a missing export function in an implicitly dependent module. Error: Modules with different CPU types were found. Error: A circular dependency was detected. Warning: At least one delay-load dependency module was not found. Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.
EDIT
This really fixed it:
dll_name = "C:/Users/Desktop/SOURCE/build/libmy_library.dll"
dll_handle = win32api.LoadLibraryEx(dll_name, 0, win32con.LOAD_WITH_ALTERED_SEARCH_PATH)
my_lib = ctypes.WinDLL(dll_name, handle=dll_handle)

Related

Error when using winshell module: No module named 'win32'

import winshell
r = list(winshell.recycle_bin())
for index, value in enumerate(r):
print(index, value.original_filename())
This is the simple script I wrote, but when I try running it (or antyhing else that uses winshell) I get this error:
ModuleNotFoundError: No module named 'win32'
And when I try running pip install win32 I get another error:
ERROR: Could not find a version that satisfies the requirement win32 (from versions: none)
ERROR: No matching distribution found for win32
So now I'm even more confused. Why does winshell need a different module? That module doesn't even exist. Is it fine if I use some different module than the non-existent win32? If so which one? What am I supposed to do now?
First, you have to execute the script inside the Scripts directory, the pywin32_postinstall.py. Let’s say your Python directory is C:\python3, just follow the code below.
cd C:\python3
python Scripts/pywin32_postinstall.py -install
After that, the installation will drop the DLL files under the C:\Windows\System32. You need to move those two files ( pythoncom310.dll and pywintypes310.dll) to C:\python3\Lib\site-packages\win32 directory.
After that, you need to edit the python310._pth that you can find inside the Python installation folder. Then make the following changes:
Lib/site-packages
Lib/site-packages/win32
Lib/site-packages/win32/lib
Lib/site-packages/pythonwin
python310.zip
#Uncomment to run site.main() automatically
#import site
Save and try running your code again.
Troubleshoot
If you still get an error saying “ImportError: DLL load failed while importing win32api: The specified module could not be found.”, make sure you have copied the two dll files to Lib\site-packages\win32 directory.
PythonWin32Api

Python generate SOABI/Extension Suffix (pep 3149) for Windows

When I compile a cython-based C-extension on MacOS/Linux, I get a .so file with a name like foo.cpython-37m-darwin.so. I can get the extension suffix using:
import sysconfig
print(sysconfig.get_config_var('EXT_SUFFIX')) # .cpython-37m-darwin.so
print(sysconfig.get_config_var('SOABI')) # cpython-37m-darwin
On windows, where I'm building the C-extensions with msys2-mingw, I get a file named foo.cp37-win_amd64.pyd, but sysconfig.get_config_var('EXT_SUFFIX') returns .pyd, and fetching the SOABI config var returns None.
Is there a way to reliably reconstruct the correct full extension suffix on windows?
It looks like distutils provides the proper information:
import distutils
print(distutils.sysconfig.get_config_var('EXT_SUFFIX')) # .cp37-win_amd64.pyd

Renamed .c files to .cpp, importing Cython library fails

I had a working Cython program which wrapped some C libraries and custom C code. Recently, I had to switch my project to C++, so I renamed all my C code to *.cpp. Cython compiled fine and produced the .so file. However, when I try to import my library in Python, I get the following error.
File "example.py", line 1, in <module>
from tag36h11_detector import detect
ImportError: dlopen(/Users/ajay/Documents/Code/calibration/apriltag_detector/examples/tag36h11_detector.cpython-36m-darwin.so, 2): Symbol not found: _free_detection_payload
Referenced from: /Users/ajay/Documents/Code/calibration/apriltag_detector/examples/tag36h11_detector.cpython-36m-darwin.so
Expected in: flat namespace
in /Users/ajay/Documents/Code/calibration/apriltag_detector/examples/tag36h11_detector.cpython-36m-darwin.so
Because I'm not sure about the source of the error, I'm not sure what relevant information to provide.
Here's my setup.py
from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy
setup(ext_modules=cythonize(Extension(
name='tag36h11_detector',
sources=["tag36h11_detector.pyx",
"tag36h11_detector/tag36h11_detector.cpp"],
include_dirs=["/usr/local/include/apriltag", numpy.get_include()],
libraries=["apriltag"])))
I compile it with python setup.py build_ext --inplace
Thanks for any assistance!
Add language=c++ to your setup:
setup(ext_modules=cythonize(Extension(
name='XXX',
....
language="c++",
)))
You probably use gcc. The frontend of gcc (and many other compilers) decides whether the file is compiled as C (cc1 is used) or C++ (cc1plus is used) depending on its extension: ".c" is C, ".cpp" is C++.
If you use extra_compile_args=["-v"], in your setup you can see exactly which compiler is used:
Cython creates "tag36h11_detector.c" and because of its extension the C-compiler (cc1) is used.
For the file "tag36h11_detector/tag36h11_detector.cpp" the C++-compiler (cc1plus) is used.`
One of the differences between C and C++ is the name mangling: C expects that the names of the symbols in the object files are not mangled, but C++ mangles it.
For example for a function with signature int test(int) C tells to the linker to search for a symbol called test, but C++ creates a symbol called _Z4testi instead, and thus it cannot be find in the linkage step.
Now, what happens during the linkage? On Linux, the default-behavior of linking a shared object is, that we can have undefined symbols. It is implicitly assumed, that those symbols will be availably during the run-time, when the shared library is loaded. That means the program fails only when the shared object is loaded and the symbol cannot be found, i.e. when you import your module.
You could add extra_link_args=["-Wl,--no-undefined"] to ensure that the compilation fails if there are undefined symbols ain order to not have any surprises during the runtime.
One way to fix it could be too say to C++-compiler to emit unmangled names using extern "C" in your code, as pointed out in the comments.
A less intrusive approach would be to make clear to compiler, that C++-convention is used by adding language="c++" to the setup.
With language="c++", Cython creates "XXX.cpp" (instead of "XXX.c") from "XXX.pyx", and thus gcc chooses C++-compiler for the cythonized file, which is aware of the right name-mangling.

Errors building Boost.Python tutorial example on Windows

I'm trying to set up Boost.Python 1.54.0 on Windows 7, python 2.7.3. I installed boost_1_54_0 and built it with Visual Studio 2010. I can build and run the quickstart and tutorial examples in the distribution (I had to add some MSVC lib dirs as library-path requirements in Jamroot, but that's OK). But when I copy the tutorial example to a different dir, not inside the boost dist dir, to make it more like a real project, bjam gives build errors. I changed the use-project boost location in Jamroot to /local/boost_1_54_0/ which is where boost wanted to install itself, and added a simple one-line boost-build.jam (based on something I found online):
boost-build C:/local/boost_1_54_0/tools/build/v2 ;
but ultimately bjam gives me this error:
% bjam
notice: no Python configured in user-config.jam
notice: will use default configuration
C:/local/boost_1_54_0/tools/build/v2/build\project.jam:262: in find-jamfile from module project
error: Unable to load Jamfile.
error: Could not find a Jamfile in directory '/local/boost_1_54_0'.
error: Attempted to find it with pattern '[Bb]uild.jam [Jj]amfile.v2 [Jj]amfile [Jj]amfile.jam'.
error: Please consult the documentation at 'http://www.boost.org'.
C:/local/boost_1_54_0/tools/build/v2/build\project.jam:280: in load-jamfile from module project
C:/local/boost_1_54_0/tools/build/v2/build\project.jam:64: in load from module project
C:/local/boost_1_54_0/tools/build/v2/build\project.jam:89: in load-used-projects from module project
C:/local/boost_1_54_0/tools/build/v2/build\project.jam:75: in load from module project
C:/local/boost_1_54_0/tools/build/v2/build\project.jam:145: in project.find from module project
C:/local/boost_1_54_0/tools/build/v2\build-system.jam:535: in load from module build-system
C:\local\boost_1_54_0\tools\build\v2/kernel\modules.jam:289: in import from module modules
C:\local\boost_1_54_0\tools\build\v2/kernel/bootstrap.jam:139: in boost-build from module
C:\tmp\tutorial\boost-build.jam:1: in module scope from module
What else do I need to add, or what am I doing wrong?
I ended up giving up on bjam for this, and just used SCons. A simple SConstruct was enough:
# SConstruct for building boost python tutorial example
import os
boost_python_lib = 'boost_python-vc100-gd-1_54'
boost_top = 'c:/boost'
python_top = 'c:/python27'
env=Environment(TARGET_ARCH='x86',
CCFLAGS=['/MDd', '/DEBUG', '/EHsc'],
CPPPATH=[os.path.join(boost_top,'include/boost-1_54'),
os.path.join(python_top, 'include')],
LIBPATH=[os.path.join(boost_top, 'lib/i386'),
os.path.join(python_top, 'libs')])
dll=env.SharedLibrary('hello_ext', 'hello.cpp',
LIBS=boost_python_lib)
env.InstallAs('hello_ext.pyd', dll[0])
# Copy the boost python lib into this dir so hello_ext will find it at runtime
env.Install('.', os.path.join(boost_top, 'lib/i386', '%s.dll'%boost_python_lib))
Of course you could make a real SCons Tool out of this, but that was enough to get me going. Hope it's useful to others.

Compiling gVim with Python 3 support

I hope this is the right place to ask this question:
I am trying to compile gVim with python 3 support using cygwin under windows:
I changed the Make_cyg.mak files Python section to the following:
##############################
# DYNAMIC_PYTHON=yes works.
# DYNAMIC_PYTHON=no does not (unresolved externals on link).
##############################
ifdef PYTHON
DEFINES += -DFEAT_PYTHON
INCLUDES += -I$(PYTHON)/include
EXTRA_OBJS += $(OUTDIR)/if_python.o
ifndef DYNAMIC_PYTHON
DYNAMIC_PYTHON = yes
endif
ifndef PYTHON_VER
PYTHON_VER = 30
endif
ifeq (yes, $(DYNAMIC_PYTHON))
DEFINES += -DDYNAMIC_PYTHON -DDYNAMIC_PYTHON_DLL=\"python$(PYTHON_VER).dll\"
else
EXTRA_LIBS += $(PYTHON)/libs/python$(PYTHON_VER).lib
endif
endif
However when running:
$ make -f Make_cyg.mak OLE=Yes PYTHON=/cygdrive/p/Applications/PortablePython_1.1_py3.0.1/App/ RUBY=/cygdrive/c/Programme/Ruby/
this results in the following errors:
In file included from /cygdrive/p/Applications/PortablePython_1.1_py3.0.1/App//i
nclude/Python.h:70,
from if_python.c:43:
/cygdrive/p/Applications/PortablePython_1.1_py3.0.1/App//include/bytesobject.h:1
04:1: warning: "F_BLANK" redefined
In file included from globals.h:1554,
from vim.h:1831,
from if_python.c:20:
farsi.h:74:1: warning: this is the location of the previous definition
if_python.c:729: warning: initialization makes integer from pointer without a ca
st
if_python.c:733: warning: initialization from incompatible pointer type
if_python.c:734: warning: initialization from incompatible pointer type
if_python.c:735: warning: initialization from incompatible pointer type
if_python.c:737: error: `cmpfunc' undeclared here (not in a function)
if_python.c:737: error: initializer element is not constant
if_python.c:737: error: (near initialization for `OutputType.tp_repr')
if_python.c:737: error: parse error before numeric constant
/** more errors **/
if_python.c:2256: warning: initialization from incompatible pointer type
if_python.c:2257: warning: initialization from incompatible pointer type
if_python.c: In function `PythonMod_Init':
if_python.c:2351: error: structure has no member named `ob_type'
if_python.c:2352: error: structure has no member named `ob_type'
if_python.c:2353: error: structure has no member named `ob_type'
if_python.c:2354: error: structure has no member named `ob_type'
if_python.c:2355: error: structure has no member named `ob_type'
if_python.c:2356: error: structure has no member named `ob_type'
make: *** [gobj/if_python.o] Error 1
I am using a portable python install from Portable Python. I don't know if that may be the source of the error.
I am hoping someone knows how to compile vim with python 3 support (if I only compile it with ruby support it compiles nicely).
Thanks in advance,
Gjallar
I have compiled vim with python3 support. Here is the Patch updated for vim 7.2.411.
For compilation instruction check out my 2009 September 22 mail on
groups.google.com/group/vim_dev/browse_frm/month/2009-09
(adding a second hyperlink didn't work)
There is a lot of things going on at once here. First of all, why do you want Python 3.0? If you really want Python 3, then you should use Python 3.1.
Second of all, what does "Python 3 support" mean in the case of gVim? Is it to make extensions with Python? Then you don't want Python 3 support, as any extension that exists for gVim is going to be written for Python 2.
And yeah, it seems very strange to use portable python. Since you are compiling gVim with cygwin, you should reasonably use a Python compiled with the same Cygwin.
Doesn't the normal gvim for Windows have Python support?

Categories

Resources