繁体   English   中英

在Linux和Windows中与C#集成的跨平台C ++

[英]Cross platform c++ integrated with c# in Linux and Windows

我在C ++中有以下代码来确定OS中的可用RAM

#if defined(_WIN32)
#include <stdio.h>
#include <windows.h>
#include "string.h"
#include "setjmp.h"
#elif defined(__linux__)
#include "stdio.h"
#include "string.h"
#include <unistd.h>
#endif

extern "C"
{
    unsigned long long getAvailableSystemMemory_Windows64();
    unsigned long long getAvailableSystemMemory_Linux64();
}

#if defined(_WIN32)

__declspec(dllexport) extern unsigned long long getAvailableSystemMemory_Windows64()
{

MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
return status.ullAvailPhys / 1024 / 1024;
}

#elif defined(__linux__)

extern unsigned long long getAvailableSystemMemory_Linux64()
{

unsigned long long ps = sysconf(_SC_PAGESIZE);
unsigned long long pn = sysconf(_SC_AVPHYS_PAGES);
unsigned long long availMem = ps * pn;
return availMem / 1024 / 1024;
}

#endif

int main()
{
#if defined(_WIN32)
    printf("%d", getAvailableSystemMemory_Windows64());
#elif defined(__linux__)
    printf("%d", getAvailableSystemMemory_Linux64());

#endif
printf("MB");

int a;
scanf("This is the value %d", &a);
}

和下面的代码在C#中

class Program
{

    [DllImport("hello.dll", CallingConvention = CallingConvention.Cdecl)]
    extern static long getAvailableSystemMemory_Windows64();


    [DllImport("hello.so", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "getAvailableSystemMemory_Linux64")]
    extern static long getAvailableSystemMemory_Linux64();

    static void Main(string[] args)
    {
        long text = 0;
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            text = getAvailableSystemMemory_Windows64();
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            text = getAvailableSystemMemory_Linux64();


        Console.WriteLine(text);
        Console.WriteLine("Hello World!");
        Console.ReadLine();
    }

}

然后在Windows中,我使用g++ --shared -o hello.dll hello.cpp编译c ++代码,并将dll复制到debug文件夹。 一切都好。

对于Linux,我使用g++ -o hello.so hello.cpp在Opensuse上进行编译,然后将.so文件复制到调试中,但是它不起作用。 我例外

Unhandled Exception: System.DllNotFoundException: Unable to load shared 
library 'hello.so' or one of its dependencies. In order to help diagnose 
loading problems, consider setting the LD_DEBUG environment variable: 
libhello.so.so: cannot dynamically load executable
at CallCDll.Program.getAvailableSystemMemory_Linux64()
at CallCDll.Program.Main(String[] args) in 
/home/CallCDll/Program.cs:line 22

我使用LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/CallCDll/bin/Debug/netcoreapp2.2.so文件目录路径添加到LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/CallCDll/bin/Debug/netcoreapp2.2但不起作用。

我该怎么办? 无论我将.so文件复制到哪里,都找不到它。

根据[man7]:GCC(1)man gcc ):

-共享

产生一个共享对象,然后可以将其与其他对象链接以形成可执行文件。 并非所有系统都支持此选项。 为了获得可预测的结果,在指定此链接器选项时,还必须指定用于编译的相同选项集( -fpic-fPIC或model子选项)。[1]

因此,您的命令不是生成共享对象或库( .so ),而是生成可执行文件(即使命名为hello.so )。 如果尝试运行它,则会看到main的输出。
要解决问题,请将您的构建命令更改为:

g++ -shared -fPIC -o hello.so hello.cpp

其他说明

  • 不知道为什么要使函数外部化
  • 关于__declspec(dllexport)跨平台处理它的常用方法是通过宏。 有很多例子(我也有几个例子),这是一个例子: [SO]:Python ctypes返回一个函数指针数组(@CristiFati的回答)DLL00_EXPORT宏)
  • 在命名方面,通常将一个库(我们称为“ example ”)命名为lib example.so 为了向后兼容,许多lib仍被这样命名,就我个人而言,我只会看到一个优点:当与它链接时,仅指定短版本( -lexample )而不是其名称。
    如果决定更改名称,请确保也更新C#代码: [DllImport("libhello.so", ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM