Importing a dll in python on Ubuntu - python

I am using python 2.6.5 on an Ubuntu intalled server.
I need to integrate an API for our applicaion, in that case, i needed to use a DLL given to me by the API provider. Their example of code about api integration is written in Visual Basic... I made a search on google and found some examples of using ctypes , and i try using cdll and pydll, which caused the following error...
OSError: /home//some.dll: invalid ELF header
One possibility is using IronPython, but i do not have much information about ironpython so i am not sure if it will handle my needs completely..
Is there any available module that let me use that dll on python (or aynthing that i am missing from the exixting ones). It is hard to upgrade my python version?

DLLs may be windows creatures, but if a DLL is 'pure .NET' and doesn't utilize executables specific to windows etc., then it can work often in Linux, through Mono. (mono ipy.exe).
Ironpython's System and similiar windows modules are customized to be os agnostic (to a untested degree).
I have successfully run NHibernate, FluentNHibernate, log4net, and a few other commonly used DLLS in Ubuntu.
import clr
import sys
sys.path.append(os.path.abspath('./DLL')) #where your dlls are
clr.AddReference('System')
clr.AddReference('FluentNHibernate')
from FluentNHibernate.Cfg.Db import PostgreSQLConfiguration
The key seems to be to import DLLs in this fashion. If a dll imports another (fluentnhibernate imports nhibernate), you don't need to import Nhibernate for example.

DLLs are Windows creatures. The only way you'll be able to use a DLL is by using a Windows build of Python. You'll be able to run Windows Python on Ubuntu by having Windows installed inside a virtual machine. You also might be able to run it using Wine.
An alternative, of course, is to ask your API provider if they have a Linux version of the API.

First, check if your DLL is a .NET Assembly file. An "Assembly DLL file" has nothing to do with the assembler. It's simply a way the .NET framework stores its bytecode inside a DLL file!
Do file library.dll in Linux. If it says something like this:
PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
then you're lucky: it's an assembly file. You can run it on Linux.
Install Mono. Install Python.NET. Forget IronPython: it's dead.
Now, in Python.NET, you can do this:
import clr
clr.AddReference('./library.dll')
# the library has just registered a namespace we can use
from LibraryName import *
but how do you know what to import?
Auto-complete.
Or use monop tool to inspect the DLL like this:
$ monop -r library.dll
Assembly Information:
LibraryName
Version=9.9.3.0
Culture=neutral
PublicKeyToken=null
LibraryName.ClassName
...
$ monop -r library.dll LibraryName.ClassName
public class ClassName {
public ClassName (string inputString);
...
}
and it will tell you everything about that library

Related

Python/C++ wrapper Using external dll with Pybind11

Python version: 3.8.1
Spyder version: 3.3.6
Qt version: 5.12.9
Wrapper: develop using PyBind11
I am wrapping a dll develop in C++ which use Qt dlls to be used with Python. I wrote the wrapper with Visual Studio 2019 using the compiler MSVC (as my dll is compiled with MSVC). After generating the solution in VS2019 I obtain a .pyd file which can be import with python.
It works good when I use python on line command:
Start cmd.exe
$python
import MyLibName
I can use the functions/classes ...
But if I try with Spyder, I get the following error:
ImportError: DLL load failed while importing PyStack: The specified module could not be found..
So here are my questions :
Is there a way to get more information about ImportError like the name of the missing dll or something?
I don't understand why the issue only happen with spyder. I tried with IPython Qt Console and it work. Does spyder use a embeded python version or something ?
I don't fully understand how dll shall be managed, I mean shall I provide dll like libGLESV2.dll with the .pyd or just give a path where to find it ?
Thank you in advance.
My guess
I think I find out which part of Qt/python is producing this issue, but I still don't know how to solve it.
My dll use signals/slots which need an event loop to be performed. If an event loop is already running the dll will try to use it, if the loop version (ex : PyQt5==5.14.1) isn’t the same as mine (ex Qt==5.15.1) import will be impossible.
Note that the reverse is true, if I run my dll an then try to start a loop with %gui qt the command will throw an error.
How to reproduce the issue :
Compile a Qt project available here.
Copy the output dll in the folder PyMyStack/dependencies of the VS Project (available here)
Compile the VS project.
Open an IPython console (without using qt has event loop)
Import the module created with VS (Import PyMyStack)
Run the magic command %gui qt
Last command shall print : ERROR:root:DLL load failed while importing QtSvg: The specified procedure could not be found.
How to hide/solve the problem:
Disclaimer : The solutions presented here are surely not the best, if you know a better one please share it ☺
If you just want to import your lib in Spyder, you can use another event loop. Here are the steps to change this:
In Spyder menus go to Tools→Preferences
Select “IPython console”
Go to “Graphics” tab and change the backend combo box to any other values than Qt or Automatic
If you want to use Qt event loop you will have to update it. You can do this with pip command, but remember than Spyder is not compatible with some version. Here is the pip command:
Pip install PyQt5==X.Y.Z
Where X and Y are the same version use to compile your Qt project. The last digit version seems to not be important.

Use And Import .SO Native Library From Apk In Python

How do I import and use an .SO file that I extracted from apk file?
I've used ctypes library in Linux but it gave me error on every way I tried it.
There are 2 version of the .so files: arm64, and armeabi.
When i tried import the armeabi version, which is 32-bit, it gave me
wrong ELF class: ELFCLASS32
and so I try the arm64, and somehow I got
cannot open shared object file: No such file or directory
I can assure you it is not a typo path, I tried to copy it using the same path. but I cannot import it because no such file.
code:
import ctypes
def main():
TestLib = ctypes.CDLL('/home/manalkaff/Desktop/arm64-v8a/nativelibrary.so')
if __name__ == '__main__':
main()
Is this how I am supposed to do it? Or there is another way?
You can try to decompile and port your shared object to x86. To do this you should load your binary in Ghidra and extract all the functions except utility ones like JNI initialization etc. which will be inserted by compiler automatically if required. Then rebuild using compiler and IDE of your choice like Clion + Clang. Not forget to fix some errors and switch to Windows API if Android API was used. This will require some time and effort though, depending on amount of functions and size of binary (except support stuff once again).
You can't load and execute ARM code on x86 CPU. You need a virtual machine that will emulate ARM CPU for that.
Even after loading the .so file on Linux ARM, you might still be missing some Android dependencies. Use ldd copied.so to see which.

How to load portable .NET library within Iron Python script?

I have serious troubles loading a portable .NET library (to be used in standard .NET and Silverlight environment) from a Python script.
.NET DLL file version is 4.0.3.319.233 (System.Core.DLL), IronPython is 2.7.1, running in 32bit/x86 mode. Visual Studio 2010 with C# under .NET 4. Microsoft .NET update KB2468871 for Portable library usage is also installed (Version 2).
If I try to load the library from the Python script:
clr.AddReferenceToFileAndPath(UsedPath+"\\MyNamespace\\MyPortableLibrary.dll")
it can't be accessed, and when the script reaches a type, it says:
"attribute [type in portable assembly] of 'namespace#' is read-only"
indicating the assembly has not been loaded at all (or as Silverlight, and can't be used by the Python script).
Changing the code to: (Assembly class from System.Reflection)
PortableAssembly = Assembly.LoadFrom(UsedPath+"\\MyNamespace\\MyPortableLibrary.dll") # load through .NET Reflection, Python won't load Portable assembly properly!
clr.AddReference(PortableAssembly)
results in an error:
exceptions.IOError occurred
Message: [Errno 2] Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The system cannot find the file specified.
The last code seems to work, when the Python script is called automatically from within another .NET program, instantiating it's own Python engine, but gives the above error when the script is executed from a Python project in Visual Studio. Python settings in VisualStudio, Tools\Options\Python Tools\Interpreter Options are for x86/32bit mode. All environment parameters show that .NET 4 is used.
I've got multiple ways now to fix it from a C#/.NET generated Python engine, but how can I load the portable assembly in a basic IronPython runtime environment, so that it works in the correct .NET 4 environment, not trying to load any .NET 2 stuff?
Update:
I restarted and rebuilt my portable library after the MS KB2468871 update, and also uninstalled IronPython and Python tools for VS, replacing them by versions 2.7.3 and 1.5 (VS2010). The error with 'System.Core, Version=2.0.5.0' still occurs.
The FileNotFoundException is an indication that something is loading the assemblies using Assembly.LoadFile instead of Assembly.LoadFrom, but not handling assembly policy correctly. I'm not sure how Python code in Visual Studio works, but if you are able to run any bootstrapper code before the portable assembly has been loaded, try the code that I showed here:
PCL Retargetable Assembly not redirected inside MS CRM Plugin.
use sys.path to add pathes to where your .net dlls are:
import sys
sys.path.append("c:\MyDotNetDir");
import clr
clr.AddReference("MyDotNetAssembly.dll")
# do not forget to import the namespace
import Erik.MyDotNetAssemblyNamespace
inst = Erik.MyDotNetAssemblyNamespace.MyDotNetObject()

Python for .NET "unable to find assembly" error

I'm using CPython and I have a C# dll. I'm trying to use Python for .NET to make them talk. I can't use IronPython because I need to integrate this into an existing CPython system.
I'm completely new to Python for .NET, and I actually have very little experience with Python and no experience with C#. So please forgive me if my question seems very basic.
I'm using Python 2.7.3, and I downloaded
pythonnet-2.0-alpha2-clr2.0_131_py27_UCS2 and unzipped it into a folder named pyfornet_test, which also contains the dll I'm trying to use (called DotNet4Class.dll)
Then I run this:
import sys
import os
import clr
sys.path.append(r"C:\pyfornet_test")
clr.AddReference("DotNet4Class.dll")
Which gives me this error:
System.IO.FileNotFoundException: Unable to find assembly 'DotNet4Class.dll'.
at Python.Runtime.CLRModule.AddReference(String name) in C:\Users\Barton\Documents\Visual Studio 2008\Projects\PyShar
p\trunk\pythonnet\src\runtime\moduleobject.cs:line 375
Any advice would be much appreciated. Thank you!
One reason can be Windows was not enabling it to load from "external sources". To fix this:
Right-click on the .dll
"Properties"
Under "General", click "Unblock"
Try this (without extension .dll):
clr.AddReference(r"C:\pyfornet_test\DotNet4Class")
Is DotNet4Class.dll built against .NET 4? I assume so based on the naming of the dll.
Note the issue here: http://sourceforge.net/tracker/?func=detail&aid=3293169&group_id=162464&atid=823891
clr.AddReference fails when assembly is built with .NET 4.0 - ID: 3293169
I'd read the solution, but essentially, you need to rebuild and recompile the python for .NET project under .NET 4.
I'll also mention that projects like this, that aren't actively developed and used by lots of people, generally have subtle idiosyncrasies that make knowledge of the platform essential to work around problems such as this. It sounds like you're trying to hack this solution in without understanding much about python or .NET which is always going to be fraught with problems.
Did you try clr.FindAssembly?
import clr
import sys
assemblydir = r"C:\pyfornet_test"
assemblypath = r"C:\pyfornet_test\DotNet4Class.dll"
sys.path.append(assemblydir)
clr.FindAssembly(assemblypath)
I don't know why it works, but this code works on my computer (Python 2.7, .NET4)
I have code like this (I copied MyRightClickMenuService.dll to the same directory as my script.py). It is built against .Net 4.0.
# script.py
import clr
import os
import sys
sys.path.append(os.path.dirname(__file__))
clr.AddReference('MyRightClickMenuService')
clr.AddReference('System')
clr.AddReference('System.Security')
from MyRightClickMenuService import (
AclSecuredNamedPipeBinding,
MyMenuItem,
MyContextMenuService,
etc
)
Checklist
The folder(s) containing the DLL(s) is/are added to sys.path before loading. You may append, or sys.path.insert(0, dll_folder) to put it first on the list.
You call clr.AddReference('my_dll') without the dll extension (for my_dll.dll), after adding the folder to sys.path
The DLL Target Architecture is the same as the CPython version bitness. That is, if Architecture is x64, use 64-bit python, and if Architecture is x86, use 32-bit python. (instructions for this below)
How to check target Architecture for DLL?
I Used ILSpy (free and open source) -> Open DLL -> Check the output. Below example output.
What worked for me was to Unblock the dll file.
if u download the dll file or took it from different computer it might be blocked. So unblocked solved the issue for me.
To unblock right click on the properties if the dll file and check the Unblock box at the bottom

Tkinter OpenGL context in Python

I need to create an OpenGL context in Tkinker, for using it with PyOpenGL Python module.
Tkinker doesn't natively support OpenGL context, but I found this page on PyOpenGL docs, explaining how to use a wrapper included in the module for this:
http://pyopengl.sourceforge.net/documentation/context/
I tried to run the provided code but I got a message saying TOGL module was not found.
I downloaded the module from http://togl.sourceforge.net/, but couldn't get it to work.
PS. I did the test on Mac OS X, with Python 3.2, using virtualenv.
PyOpenGL provides Python bindings for the Tk OpenGL widget (Togl) but not Togl itself, that is why you had to download it. Now, to install Togl is easy but there isn't a tool ready to perform the task. Since the Python bindings will use Tcl to load the Togl module, the widget needs to live in one of the directories present in Tcl's auto_path, which is where Tcl looks for loading libraries. What you can do is start a Tcl interpreter, tclsh, and check which are these directories by doing puts $auto_path. In my case I copied the directory lib/Togl2.0 (inside the Togl's .tar.gz) to /opt/local/lib/tcl8.5. You can also extend auto_path to look for other directories, but I'm not covering that here.
Then I tested using Python 2.7 on Mac OSX. Doing import OpenGL.Tk tries to load Togl, too bad it fails. The reason is that Togl comes precompiled for i386, since I built Python as a universal binary all I did was run it as arch -i386 python2.7, and now import OpenGL.Tk works.

Categories