diff --git a/python/cppjit/__init__.py b/python/cppjit/__init__.py index 6280d6e..6193fc1 100644 --- a/python/cppjit/__init__.py +++ b/python/cppjit/__init__.py @@ -278,10 +278,10 @@ def macro(cppm): def load_library(name): """Explicitly load a shared library.""" - with _stderr_capture() as err: - result = gbl.Cpp.LoadLibrary(name, True) + reason = gbl.std.string() + result = gbl.Cpp.LoadLibrary(name, True, reason) if result == False: # noqa: E712 - raise RuntimeError('Could not load library "%s": %s' % (name, err.err)) + raise RuntimeError('Could not load library "%s": %s' % (name, reason)) return True diff --git a/test/test_basic_api.py b/test/test_basic_api.py index 10e2e81..c85d0fc 100644 --- a/test/test_basic_api.py +++ b/test/test_basic_api.py @@ -1,9 +1,10 @@ +import os import shutil import tempfile import py -from pytest import raises -from support import setup_make +from pytest import mark, raises +from support import IS_LINUX, setup_make # reuse the example01 currpath = py.path.local(__file__).dirpath() @@ -57,6 +58,24 @@ def test03_add_library_path(self): shutil.copyfile(test_dct + ".so", tpath + "/test.so") cppjit.load_library("test.so") + @mark.skipif(IS_LINUX == 0, reason="checks Linux dlerror text") + def test03a_load_library_failure_reason(self): + """load_library reports the loader's failure reason""" + + import cppjit + + with tempfile.TemporaryDirectory() as tpath: + missing = os.path.join(tpath, "libdlerrmissing.so") + with raises(RuntimeError, match="libdlerrmissing.*library not found"): + cppjit.load_library(missing) + + # a truncated ELF header: found on disk, rejected before dlopen + invalid = os.path.join(tpath, "libdlerrinvalid.so") + with open(invalid, "wb") as out: + out.write(b"\x7fELF" + b"\0" * 12) + with raises(RuntimeError, match="libdlerrinvalid"): + cppjit.load_library(invalid) + def test04_add_include_path(self): import cppjit