How to call functions in. so file in Linux (Ubuntu) system

 

In my code,I'm trying to import funtion like:

#import "libsro.so"

   int TrainNetwork(int inputSize, double& data[], int Bars, int training_bars, int BarfeatureCount);//---check

   void GetTrainingProgress(double &accuracy, double &progress, double &average_loss);

   bool IsTraining();

   double PredictNextBar(int inputSize, double& data[], int Bars, int training_bars, int BarfeatureCount);

#import

The compilation of the expert program has been successful.

But when i run the expert,I have received the following feedback

I'm sure the libsro.so is 64-bit version:

file libsro.so

libsro.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=3a93d3f2e299a0ffed5e86d747a1b79bf016d650, not stripped

Some components of CUDA, such as NCCL, cannot run on Windows, so the. so file is an important attempt.

So, how can i use .so file in my expert? 

 
Jia Run Yuan:

In my code,I'm trying to import funtion like:

#import "libsro.so"

   int TrainNetwork(int inputSize, double& data[], int Bars, int training_bars, int BarfeatureCount);//---check

   void GetTrainingProgress(double &accuracy, double &progress, double &average_loss);

   bool IsTraining();

   double PredictNextBar(int inputSize, double& data[], int Bars, int training_bars, int BarfeatureCount);

#import

The compilation of the expert program has been successful.

But when i run the expert,I have received the following feedback

I'm sure the libsro.so is 64-bit version:

file libsro.so

libsro.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=3a93d3f2e299a0ffed5e86d747a1b79bf016d650, not stripped

Some components of CUDA, such as NCCL, cannot run on Windows, so the. so file is an important attempt.

So, how can i use .so file in my expert? 

WINE is a windows environment. Metatrader is a windows binary. It can only load DLL files as library.

You will need to write a function router DLL, with code that's capable of loading a .so file from Linux.

Then you can load this wrapper DLL in Metatrader, which exports the functions from the loaded .so library.
 
Dominik Egert #:
WINE is a windows environment. Metatrader is a windows binary. It can only load DLL files as library.

You will need to write a function router DLL, with code that's capable of loading a .so file from Linux.

Then you can load this wrapper DLL in Metatrader, which exports the functions from the loaded .so library.

Hi, Dominik Egert.Thank you for providing the idea. Follow your idea, I have made multiple attempts at the code of the wrapper. But i failed. For example, the following is one of the representative attempts of my code:

#include <windows.h>
#include <string>
#include <stdexcept>

// Function pointers
extern "C" {
    typedef int (*TrainNetworkFunc)(int, double*, int, int, int);
    typedef void (*GetTrainingProgressFunc)(double*, double*, double*);
    typedef bool (*IsTrainingFunc)();
    typedef double (*PredictNextBarFunc)(int, double*, int, int, int);
}


TrainNetworkFunc g_TrainNetwork = nullptr;
GetTrainingProgressFunc g_GetTrainingProgress = nullptr;
IsTrainingFunc g_IsTraining = nullptr;
PredictNextBarFunc g_PredictNextBar = nullptr;

HMODULE g_hModule = nullptr;

bool LoadLibraryAndFunctions() {
    if (g_hModule) return true; // Already loaded

    g_hModule = LoadLibrary("/usr/local/lib/libsro.so");
     
    if (!g_hModule) {
        return false;
    }

    g_TrainNetwork = (TrainNetworkFunc)GetProcAddress(g_hModule, "TrainNetwork");
    g_GetTrainingProgress = (GetTrainingProgressFunc)GetProcAddress(g_hModule, "GetTrainingProgress");
    g_IsTraining = (IsTrainingFunc)GetProcAddress(g_hModule, "IsTraining");
    g_PredictNextBar = (PredictNextBarFunc)GetProcAddress(g_hModule, "PredictNextBar");

    return (g_TrainNetwork && g_GetTrainingProgress && g_IsTraining && g_PredictNextBar);
}

void UnloadLibrary() {
    if (g_hModule) {
        FreeLibrary(g_hModule);
        g_hModule = nullptr;
        g_TrainNetwork = nullptr;
        g_GetTrainingProgress = nullptr;
        g_IsTraining = nullptr;
        g_PredictNextBar = nullptr;
    }
}

extern "C" {
    __declspec(dllexport) int __stdcall TrainNetwork(int inputSize, double* data, int Bars, int training_bars, int BarfeatureCount) {
        if (!LoadLibraryAndFunctions()) {
            return -2;
        }
        return g_TrainNetwork(inputSize, data, Bars, training_bars, BarfeatureCount);
    }

    __declspec(dllexport) void __stdcall GetTrainingProgress(double* accuracy, double* progress, double* average_loss) {
        if (LoadLibraryAndFunctions()) {
            g_GetTrainingProgress(accuracy, progress, average_loss);
        }
    }

    __declspec(dllexport) bool __stdcall IsTraining() {
        if (LoadLibraryAndFunctions()) {
            return g_IsTraining();
        }
        return false;
    }

    __declspec(dllexport) double __stdcall PredictNextBar(int inputSize, double* data, int Bars, int training_bars, int BarfeatureCount) {
        if (LoadLibraryAndFunctions()) {
            return g_PredictNextBar(inputSize, data, Bars, training_bars, BarfeatureCount);
        }
        return -1.0;
    }
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
        switch (ul_reason_for_call) {
            case DLL_PROCESS_ATTACH:
                // Initialize
                break;
            case DLL_THREAD_ATTACH:
                break;
            case DLL_THREAD_DETACH:
                break;
            case DLL_PROCESS_DETACH:
                UnloadLibrary();
                break;
        }
        return TRUE;
    }
//FINISH All

I use x86_64-w64-mingw32-g++ -shared -o sro_wrapper.dll ../sro_wrapper.cpp -lkernel32 to compile it, and i got  sro_wrapper.dll.  I put the dll in Libraries of MQL5(in wine),but when i run the expert, the  sro_wrapper.dll can't use functions in libsro.so.

I have had discussions with Claude3.5 and GPT-4o from various angles, and have also tried various solutions. In the end, it seems that the solution has been stabilized in the following code:

#include <windows.h>
#include <iostream>
#include <string>

// 声明Wine特定的函数
extern "C" void* wine_dlopen(const char* filename, int flag);
extern "C" void* wine_dlsym(void* handle, const char* symbol);
extern "C" int wine_dlclose(void* handle);

// 定义RTLD_NOW,因为MinGW可能没有定义它
#ifndef RTLD_NOW
#define RTLD_NOW 2
#endif

// 函数指针类型定义
typedef int (*TrainNetworkFunc)(int, double*, int, int, int);
typedef void (*GetTrainingProgressFunc)(double*, double*, double*);
typedef bool (*IsTrainingFunc)();
typedef double (*PredictNextBarFunc)(int, double*, int, int, int);

// 全局函数指针
TrainNetworkFunc g_TrainNetwork = nullptr;
GetTrainingProgressFunc g_GetTrainingProgress = nullptr;
IsTrainingFunc g_IsTraining = nullptr;
PredictNextBarFunc g_PredictNextBar = nullptr;

void* g_hModule = nullptr;

bool LoadLibraryAndFunctions() {
    if (g_hModule) return true;  // 已经加载过了

    const char* libPath = "/usr/local/lib/libsro.so";
    g_hModule = wine_dlopen(libPath, RTLD_NOW);
    if (!g_hModule) {
        std::cerr << "Failed to load libsro.so" << std::endl;
        return false;
    }

    g_TrainNetwork = (TrainNetworkFunc)wine_dlsym(g_hModule, "TrainNetwork");
    g_GetTrainingProgress = (GetTrainingProgressFunc)wine_dlsym(g_hModule, "GetTrainingProgress");
    g_IsTraining = (IsTrainingFunc)wine_dlsym(g_hModule, "IsTraining");
    g_PredictNextBar = (PredictNextBarFunc)wine_dlsym(g_hModule, "PredictNextBar");

    if (!g_TrainNetwork || !g_GetTrainingProgress || !g_IsTraining || !g_PredictNextBar) {
        std::cerr << "Failed to load one or more functions from libsro.so" << std::endl;
        wine_dlclose(g_hModule);
        g_hModule = nullptr;
        return false;
    }

    return true;
}

// 导出函数
extern "C" {
    __declspec(dllexport) int __stdcall TrainNetwork(int inputSize, double* data, int Bars, int training_bars, int BarfeatureCount) {
        if (!LoadLibraryAndFunctions()) {
            return -2;
        }
        return g_TrainNetwork(inputSize, data, Bars, training_bars, BarfeatureCount);
    }

    __declspec(dllexport) void __stdcall GetTrainingProgress(double* accuracy, double* progress, double* average_loss) {
        if (LoadLibraryAndFunctions()) {
            g_GetTrainingProgress(accuracy, progress, average_loss);
        }
    }

    __declspec(dllexport) bool __stdcall IsTraining() {
        if (LoadLibraryAndFunctions()) {
            return g_IsTraining();
        }
        return false;
    }

    __declspec(dllexport) double __stdcall PredictNextBar(int inputSize, double* data, int Bars, int training_bars, int BarfeatureCount) {
        if (!LoadLibraryAndFunctions()) {
            return -2.0;
        }
        return g_PredictNextBar(inputSize, data, Bars, training_bars, BarfeatureCount);
    }
}

// 在DLL卸载时释放资源
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    switch (fdwReason) {
        case DLL_PROCESS_DETACH:
            if (g_hModule) {
                wine_dlclose(g_hModule);
                g_hModule = nullptr;
            }
            break;
    }
    return TRUE;
}
//FINISH All

But I can't compile it. Because wine_dlopen,wine_dlsym are internal functions of wine, and I haven't found a way to call it yet.

I've been crazy about this problem these past few days.

Can you give me some tips, articles, or examples?

 
Jia Run Yuan #:
wine_dlopen(libPath, RTLD_NOW)
Here you will find your route to go.


Read the section: "Building Winelib DLLs"
 
Dominik Egert #:
Here you will find your route to go.


Read the section: "Building Winelib DLLs"

This is exactly the direction I am striving for. Thank you!