Python and C++ (Pybind11): Python Extension Module Import Error - python

I try to wrap a C++ - function with pybind to create a python-module. After compiling with Visual Studio I accomplished to create a .pyd file.
I tried to import this file (python>>> import pymodule) but get this error:
Import Error: dynamic module does not define module export function (PyInit_pymodule)
Is it usually the right approach to import a .pyd file the way I explained above? Why do I get this error?

1a) You have to copy the .pyd file into the Python-installation folder (Lib-> side packages).
1b) You can open Python in the same folder where the .pyd - file is placed.
2) the python module must have the same name as the directory defined in CMake

Related

ERROR when trying to compile protoc files: file not found or had errors

I am trying to compile protoc files using this command:
protoc/bin/protoc models/research/object_detection/protos/*.proto --python_out=.
but I am getting this output on cmd
object_detection/protos/flexible_grid_anchor_generator.proto: File not found.
object_detection/protos/grid_anchor_generator.proto: File not found.
object_detection/protos/multiscale_anchor_generator.proto: File not found.
object_detection/protos/ssd_anchor_generator.proto: File not found.
models/research/object_detection/protos/anchor_generator.proto:5:1: Import "object_detection/protos/flexible_grid_anchor_generator.proto" was not found or had errors.
models/research/object_detection/protos/anchor_generator.proto:6:1: Import "object_detection/protos/grid_anchor_generator.proto" was not found or had errors.
models/research/object_detection/protos/anchor_generator.proto:7:1: Import "object_detection/protos/multiscale_anchor_generator.proto" was not found or had errors.
models/research/object_detection/protos/anchor_generator.proto:8:1: Import "object_detection/protos/ssd_anchor_generator.proto" was not found or had errors.
models/research/object_detection/protos/anchor_generator.proto:14:5: "GridAnchorGenerator" is not defined.
models/research/object_detection/protos/anchor_generator.proto:15:5: "SsdAnchorGenerator" is not defined.
models/research/object_detection/protos/anchor_generator.proto:16:5: "MultiscaleAnchorGenerator" is not defined.
models/research/object_detection/protos/anchor_generator.proto:17:5: "FlexibleGridAnchorGenerator" is not defined.
So what can be the problem
Thank you
You need to run the protobuf compiler in the correct directory. In that case, it would be models/research:
$ cd models/research
$ ../../protoc/bin/protoc object_detection/protos/*.proto --python_out=.
The protobuf files will be compiled to python. In the directory object_detection/protos/, you should have python files named after the protobuf file (i.e <name_protobuf>_pb2.py).
There is relative imports in those protobuf files, so it's important that the protobuf compiler is run in the correct directory. You have a hint that it might be the error as the File not Found error message lists a different path than your current directory.
I faced this issue recently. I cleared it by changing the file paths in the proto file.
For example, a proto file had following imports.
import "object_detection/protos/flexible_grid_anchor_generator.proto";
import "object_detection/protos/grid_anchor_generator.proto";
import "object_detection/protos/multiscale_anchor_generator.proto";
import "object_detection/protos/ssd_anchor_generator.proto";
I changed it to the following.
import "flexible_grid_anchor_generator.proto";
import "grid_anchor_generator.proto";
import "multiscale_anchor_generator.proto";
import "ssd_anchor_generator.proto";
The reason is all the proto files are present in the same object_detection/protos folder so path is not required.
I changed the references in all the proto files and it worked.

Python: Appending system path to import the module

I am trying to import a module from the prgoram called 'Power factory" in Python. The folder where power factory file located looks as follow:
I have written a script to import the powerfactory module as follow:
import sys
sys.path.append("PAth of folder")
import powerfactory as pf
When I ran the above code, it throws the following error:
ImportError: DLL load failed while importing powerfactory: The specified module could not be found.
I copied the .dll file present in the power factory folder into the Python DLL folder but no luck. Could anyone help me where am I making the mistake?
Searching the net I found this (from here)
I am not able to import powerfactory module: DLL load failed Category:
Scripting
If an error message appears when importing the powerfactory module
stating “ DLL load failed: the specified module could not be found”,
this means that Microsoft Visual C++ Redistributable for Visual Studio
2012 package is not installed on the computer.
To overcome this problem the user should add the PowerFactory
installation directory to the os path variable within his python
script.
import os
os.environ["PATH"] = r'C:\Program Files\DIgSILENT\PowerFactory 2016;' + os.environ["PATH"]
Copy the .dll file from your digsilent folder, eg. Program Files\DIgSILENT\PowerFactory 2020 SP2A\Python\3.8\boost_python38-vc141-mt-x64-1_68.dll
and place the .dll file directly in your system!
Save it to your C:\Windows\System32 folder.
&
Save it also to your C:\Windows\SysWOW64 folder.
You should be good to go.

Error importing c module compiled with Cython into python module on Mac

I have a Cython module compiled from pyx files to c files that I am trying to import and use in a python module. I'm running python 3.6 on a Mac. When I run gcc -v the output is:
Configured with: --prefix=/Library/Developer/CommandLineTools/usr - -with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1 Apple LLVM version 10.0.1 (clang-1001.0.46.4) Target: x86_64-apple-darwin18.7.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Running python setup.py build and python setup.py install gives no errors, and the .so and .c files for the corresponding files appear in the right directory, which is on the path.
When I try to import the module, I get an error in the init file, from a line that tries to import another submodule:
from . import subModule
I've tried updating python and Cython, and I've made sure that gcc is in user/lib.
This is my setup.py file:
from Cython.Build import cythonize
setupArgs = dict(
name="module",
version="1.1.0",
description=description,
url="https://github.com/XXXX/XXXXX/module",
author="CTcue",
author_email="info#XXXXXX.com",
ext_modules=cythonize(["module/*.pyx"]),
)
# Use distutils setup
from distutils.core import setup
setup(**setupArgs)
This is the error message:
File "module/subModule.pyx", line 4, in init module.subModule
ModuleNotFoundError: No module named 'thirdModule'
The thirdModule in question has a .c file and a .so file that correspond to the .pyx file, and as far as I can tell everything is order there.
module's init.py:
__title__ = 'Pseudonomizer'
__version__ = '1.0.2'
__author__ = 'CTcue'
__license__ = 'Proprietary'
__copyright__ = 'Copyright 2016 CTcue'
from . import subModule
subModule:
import thirdModule
thirdModule.doSomething()
third module:
import re
from . import anotherModule
def doSomething:
#code that does something
Edit : In an attempt to see if the compiler is at fault, I tried to manually compile the .c file of thirdModule with "gcc thirdModule", and got the following error:
Undefined symbols for architecture x86_64:
This seems to suggest that the issue is compiler-related, but I still haven't found the solution.
Any help would be much appreciated.
It turns out #ead was right, and the problem was that the module had implicit relative imports which are no longer allowed in python 3.

Compile and use python-openzwave with open-zwave in non-standard location

I manually compiled python-openzwave to work with C++ library.
I would like to use it as Kodi addon (OpenELEC running on Pi 3), so can not use standard installation.
I've compiled everything, downloaded missing six and louie libs, and now try to run hello_world.py.
My current dirs structure is the following:
- root
- bin
- .lib
- config
Alarm.o
...
libopenzwave.a
libopenzwave.so
libopenzwave.so.1.4
...
- libopenzwave
driver.pxd
group.pxd
...
- louie
__init__.py
dispatcher.py
...
- openzwave
__init__.py
command.py
...
six.py
hello_world.py
But when I run hello_world.py, I get the following error -
Traceback (most recent call last):
File "hello_world.py", line 40, in <module>
from openzwave.controller import ZWaveController
File "/storage/.kodi/addons/service.multimedia.open-zwave/openzwave/controller.py", line 34, in <module>
from libopenzwave import PyStatDriver, PyControllerState
ImportError: No module named libopenzwave
If I move libopenzwave.a and libopenzwave.so to root folder, then I get the following error:
Traceback (most recent call last):
File "hello_world.py", line 40, in <module>
from openzwave.controller import ZWaveController
File "/storage/.kodi/addons/service.multimedia.open-zwave/openzwave/controller.py", line 34, in <module>
from libopenzwave import PyStatDriver, PyControllerState
ImportError: dynamic module does not define init function (initlibopenzwave)
What is wrong with my setup?
In general the steps required consist of calls to make build which handles building the .cpp files for openzwave and downloading all dependencies (including Cython); and make install which runs the setup-api, setup-lib.py (this setup script also creates the C++ Python extention for openzwave), setup-web.py and setup-manager.py.
Since you cannot run make install as you specified and are instead using the archive they provide, the only other options for creating the python extention, after building the openzwave library with make build, is generating the .so files for it without installing to standard locations.
Building the .so for the cython extention in the same folder as the Cython scripts is done by running:
python setup.py build_ext --inplace
This should create a shared library in src-lib named libopenzwave.so (it is different from the libopenzwave.so contained in the bin/ directory) which contains all the functionality specified in the extention module. You could try adding that to the libopenzwave folder.
If you pass special compiler flags during make build for building the openzwave library you should specify the same ones when executing the setup-lib.py script. This can be done by specifying the CFLAGS before executing it (as specified here) or else you might have issues like error adding symbols: File in wrong format.
Here's the description of the python-openzwave's build from the question's perspective. Almost all the steps correspond to the root Makefile's targets.
Prerequisites. There are several independent targets with little to no organization. Most use Debian-specific commands.
Cython is not needed if building from an archive (details below)
openzwave C++ library (openzwave openzwave/.lib/ target).
Build logic: openzwave/Makefile, invoked without parameters (but with inherited environment).
Inputs: openzwave/ subtree (includes libhidapi and libtinyxml, statically linked).
Outputs: openzwave/.lib/libopenzwave.{a,so}
Accepts PREFIX as envvar (/usr/local by default)
The only effect that affects us is: $(PREFIX)/etc/openzwave/ is assigned to a macro which adds a search location for config files (Options.cpp): config/ -> /etc/openzwave/ -> <custom location>.
libopenzwave Python C extension module (install-lib target - yes, the stock Makefile cannot just build it; the target doesn't even have the dependency on the library).
Build logic: setup-lib.py
Inputs: src-lib/, openzwave/.lib/libopenzwave.a
Outputs: build/<...>/libopenzwave.so - yes, the same name as openzwave's output, so avoid confusing them
By default, openzwave is linked statically with the module so you don't need to include the former into a deployment
The module does, however, need the config folder from the library. It is included by the build script when making a package.
Contrary to what Jim says, Cython is not needed to build from an archive, the archive already includes the generated .cpp.
Now, the catch is: the module itself uses pkg_resources to locate its data. So you cannot just drop the .so and config into the currect directory and call it a day. You need to make pkg_resources.get_distribution('libopenzwave') succeed.
pkg_resources claims to support "normal filesystem packages, .egg files, and unpacked .egg files."
In particular, I was able to pull this off: make an .egg (setup-lib.py bdist_egg), unpack it into the current directory and rename EGG-INFO into libopenzwave.egg-info (like it is in site-packages). A UserWarning is issued if I don't specifically add the .so's location into PYTHON_PATH/sys.path before importing the module.
openzwave,pyozwman and pyozwweb Python packages (install)
these are pure Python packages. The first one uses the C extension module, others use the first one.
Build logic: setup-api.py,setup-manager.py,setup-web.py
Input: src-*/
Output: (pure Python)
They only use pkg_resources.declare_namespace() so you're gonna be fine with just the proper files/dirs on sys.path without any .egg-info's

python/cython compiling pyx: fatal error: capsule.h: No such file or directory

I recently worked on a python project where I need to import some .pyx files.
However, I had a hard time import it as .pyx and compile it with the following lines:
import pyximport
pyximport.install()
from . import kl
The error is
fatal error: capsule.h: No such file or directory
And in the kl.pyx file, capsule.h is used as following:
cdef extern from "capsule.h":
void* Capsule_AsVoidPtr(object ptr)
I am not sure what I should do. Please help me a little bit.
Alternatively, is it possible that the python script could import compiled .c (in Linux) file directly, instead of importing .pyx and compile it?
When I compile it with command line, it is compiled successfully, but I don't know how my IDE (PyCharm) could import that .c file.
Thank you very much.
you missed some library, you need to install the source code of capsule.h.

Categories