pleiszenburg / zugbruecke

Calling routines in Windows DLLs from Python scripts running under Linux, MacOS or BSD
https://zugbruecke.readthedocs.io/en/latest/
GNU Lesser General Public License v2.1
112 stars 11 forks source link

Loading a DLL with dependencies #102

Open cojmeister opened 2 months ago

cojmeister commented 2 months ago

Hey. I've received a DLL and a corresponding Lib from a client, I don't have any access to source code and they won't provide any other solutions. I've tried running the DLL in windows through python but couldn't manage because its function are changed. So I made a CPP wrapper that linked the lib in compile time and calls the DLL in runtime. This now works in python in windows. When trying to load the DLL with zugbruecke in Linux (the environment works with other dlls) the process fails because it can't find the dependency. I've attached the dependency to the session but it still won't recognize it.

Has anyone encountered this problem?

s-m-e commented 2 months ago

Can you share a code sample of what you did and the output it created? Please set the log_level to DEBUG (see here).

cojmeister commented 2 months ago

Hey, I can't share it because it is behind my company's secure network. But I can write a mockup.

First off, I create a dll that needs another dll (no source code for the dependency) like so:

cmake_minimum_required(VERSION 3.16)
project(my_wrapper_dll LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)

add_library(my_wrapper_dll SHARED src/wrapper.cpp)

# Link against the lib if necessary
target_link_libraries(my_wrapper_dll myClosedSrc.lib)

The lib file is used in compile time, the dll in runtime.

Next I try loading it like so in python:

import zugbruecke as zb

my_session_server = zb.SessionServer()

my_session_server.load_library("./dlls/myClosedSrc.dll")
my_loaded_dll = my_session_server.load_library("./dlls/my_wrapper_dll.dll")

When running this my logs say that they manage to attach to myClosedSrc.dll but when trying to load my_wrapper_dll.dll I get an error saying that: Couldn't find DLL (or one of it's dependencies)... Try loading using the full path

The server then proceeds to shutdown.

s-m-e commented 2 months ago

DLL discovery can be a bit of a pain. Just for debugging purposes, try putting them all, your DLL and its relevant dependencies, into the current working directory. Alternatively, use symlinks. Wine attempts to follow the semantics of Windows, but there are caveats.

Second, you are passing a typical Unix path, which is something that Wine can deal with - however, it can cause issues. Try specifying a Windows path instead. There are helper functions to convert from a Unix to a Windows path and back, see here.

Last, just to make sure, zugbruecke by default assumes that you are dealing with 32 bit DLLs, which can, if used against 64 bit DLLs, present itself in all kinds of bizarre ways. This can be configured at the time of session server creation, parameter arch.

cojmeister commented 2 months ago

I tried the three things. The problem is the my DLL is looking for the other DLL, and I can't provide it a proper path to it.

I manage to load the dependency on its own properly, but once I try loading my DLL I'm guessing wine doesn't know where to look.

Symlinks don't seem to work as the problem seems to be that the dependency isn't loaded through wine.

cojmeister commented 2 weeks ago

Hey @s-m-e Would zugbruecke or wine look inside a SYSTEM32 folder or something of the kind?

s-m-e commented 2 weeks ago

In this regard, zugbruecke is sitting entirely on Wine so it depends solely on where Wine would look (and how Wine is configured). SYSTEM/SYSTEM32 is one of the folders it should check by default. The search paths can be altered, e.g. through environment variables. I believe what you're looking for is called WINEPATH. zugbruecke/wenv should happily pass it through.