Scipy / ctypes build-config: How to load lib?

2024/10/13 16:18:16

These docs have a nice example on how to compile some external C/C++ code and load this using ctypes. This works great with manual compilation (where i'm controlling the names of my library which later gets loaded).

Now how to prepare some code to be used within scipy with full incorporation into scipy's build-system? A more general github-issue does not provide the information i'm looking for (and sadly, there is not much action).

Also: i'm more interested in using ctypes (no real usage within scipy? despite numpy's explicit tools provided?), not cython which is used in all the other wrappers (i don't see any good reason for cython, except for it's common use there: my lib will only get loaded/called once and it's slow compared to potential call-overheads).

Let's assume i added a directory like:

scipy/optimize/_mylib/README
...
scipy/optimize/_mylib/src
scipy/optimize/_mylib/src/a.cpp
...
... bunch of cpp/h files

Let's touch scipy/optimize/setup.py:

from __future__ import division, print_function, absolute_importfrom os.path import joinfrom scipy._build_utils import numpy_nodepr_apidef configuration(parent_package='',top_path=None):from numpy.distutils.misc_util import Configurationfrom numpy.distutils.system_info import get_infoconfig = Configuration('optimize',parent_package, top_path)# MODIFICATION START# OTHER EXTENSIONS OMITTED # INSPIRED BY scipy.spatial: ckdtree/src & setup.pymylib_src = ['a.cpp', 'b.cpp']mylib_src = [join('_mylib', 'src', x) for x in mylib_src]mylib_headers = ['a.h', 'b.h']mylib_headers = [join('_mylib', 'src', x) for x in mylib_headers]mylib_dep = mylib_headers + mylib_srcconfig.add_extension('_mylib',sources=mylib_src,depends=mylib_dep,include_dirs=[join('_mylib', 'src')])# MODIFICATION END    return configif __name__ == '__main__':from numpy.distutils.core import setupsetup(**configuration(top_path='').todict())

Now this works in regards to:

# in scipy base-dir
python3 setup.py build_ext --inplace

which produces (within scipy.optimize):

_mylib.cpython-35m-x86_64-linux-gnu.so

and can be loaded in the interpreter (started from dir scipy.optimize)

import numpy.ctypeslib as ctl
lib = ctl.load_library('_mylib.cpython-35m-x86_64-linux-gnu.so', '.')
lib
# <CDLL '/home......._mylib.cpython-35m-x86_64-linux-gnu.so', handle X at X

Now the question

Assuming i want to add a new file:

scipy/optimize/new_alg.py

No matter what i try, i'm not able to load this one. E.g.:

# this is scipy/optimize/new_alg.py
import numpy.ctypeslib as ctl
mylib = ctl.load_library('_mylib', '.')
mylib = ctl.load_library('_mylib', '.optimize')
# ...

The second argument is probably expected to be a full-path (opposed to partials or wildcards). All my attempts failed with the general error:

OSError: no file with expexted extension

What should i do here? (goal: ready to be a real addition to scipy: multiple platforms).

Is the approach itself doomed? From a naive perspective it's promising: the expected downsides of ctypes are irrelevant for me and it's part of the standard. Additionally it got dedicated support in numpy and i control the C/C++-part, so that i can provide a simplified single-function wrapper to be called. Why isn't this used in other parts of scipy?

Answer

Inspired by numpy's sources, i'm now able to load the lib using:

import scipy as scp
import numpy.ctypeslib as ctl
lib = ctl.load_library('_mylib', scp.optimize.__file__)  # this is the magical line
myfunc = lib.myfunc

Well... at least in theory!

Against my prior assumption, my lib-build is not equivalent to a manual-compile and the function i want to load is not available (undefined symbol: myfunc). But the problem of locating the lib feels clean now and is solved for me.

https://en.xdnf.cn/q/118060.html

Related Q&A

Webfaction Django 1.4.1: easy_thumbnails 3.0b – Couldnt get the thumbnail error

I use easy_thumbnails and it works fine on a development machine but in production I get errors like shown below, when I use {% thumbnail photo.image 300x170 %} templatetag. Though can directly browse …

acronym replacement with its value using python

i have dictionary like that i need to replace acronyms in text with its value in dictionary i use this code but it doesnt give me the appropriate result when i test the function using acronyms("we…

Grako - How to do error handling?

How do I do error handling with Grako?EBNF (MyGrammar.ebnf):pattern = { tag | function }* ; tag = tag:( "%" name:id "%" ); function = function:("$" name:id "…

How get the softlayer storage credendials?

Im trying to get the Username,password and host IQN of a authorized Softlayer Network Storage. I used this python script, but the shell returns []import SoftLayerAPI_USERNAME = xxxAPI_KEY = yyyystorage…

dopy.manager.DoError: Unable to authenticate you

Im trying to configure a Virtual Machine(with Vagrant and Ansible), that needs a file.py to the full correct configuration of this machine (according to the book that Im studying),Im was using the Digi…

subprocess.Popen: OSError: [Errno 2] No such file or directory only on Linux

This is not a duplicate of subprocess.Popen: OSError: [Errno 13] Permission denied only on Linux as that problem occurred due to wrong permissions. That has been fixed and this is an entirely different…

Windows Theano Keras - lazylinker_ext\mod.cpp: No such file or directory

I am installing Theano and Keras follwing the How do I install Keras and Theano in Anaconda Python on Windows?, which worked fine for me with an older release before. Now I have upgraded to the latest…

Python Threading: Making the thread function return from an external signal

Could anyone please point out whats wrong with this code. I am trying to return the thread through a variable flag, which I want to control in my main thread. test27.pyimport threading import timelock …

Python join data lines together

Hello i have dataset a few thousand lines which is split in even and odd number lines and i cant find a way to join them together again in the same line. Reading the file and overwriting it is fine or …

How to undraw plot with Zelle graphics?

This is a code problem for Python 3.5.2 using John Zelles graphics.py:I have spent a good amount of time looking for the answer here, but just can not figure it out. The function undraw() exists just l…