代码之家  ›  专栏  ›  技术社区  ›  senz

.net core-PInvoke C共享库函数,该函数依赖于另一个共享库

  •  6
  • senz  · 技术社区  · 7 年前

    我为现有库编写了一些包装器代码( wiringPi

    我的包装库看起来像:

    #ifndef mylib_h__
    #define mylib_h__
    extern void read_sensor();
    #endif
    

    mylib。c

    #include "mylib.h"
    #include <wiringPi.h> 
    
    void read_sensor() {
        //here is the first call on the wiringPi lib
        if (wiringPiSetup() == -1)
            exit(1);
    
        ...
    }
    

    然后我使用gcc编译我的库:

    gcc -Wall -Werror -fPIC -c mylib.c
    gcc -shared -o libmylib.so mylib.o -lwiringPi
    cp libmylib.so /usr/lib/
    

    在这个库的正常C程序消耗情况下,一切正常。

    PInvoke 呼叫 read_sensor() 从该库:

    class Program 
    {
        [DllImport("wiringPi")]
        static extern int wiringPiSetup();
    
        [DllImport("mylib")]
        static extern void read_sensor();
    
        static void Main(string[] args)
        {
            wiringPiSetup();
            read_sensor();
        }
    }
    

    dontet publish -r linux-arm
    

    并抄送给我的树莓派。

    现在我执行这个C#程序,并抛出以下错误:

    ./我的程序名:符号查找错误:/usr/lib/libmylib。so:未定义符号:wiringPiSetup

    我的第一个想法是,我的程序不知道wiringPi库。所以我为这个dll添加了一个导出,并调用了 wiringPiSetup()

    我在连接时把事情搞砸了吗?

    编辑:

    ldd /usr/lib/libmylib.so

    linux-vdso.so.1 (0x7efad000)
    /usr/lib/arm-linux-gnueabihf/libarmmem.so (0x76f73000)
    libwiringPi.so => /usr/local/lib/libwiringPi.so (0x76f40000)
    libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76dff000)
    libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76d84000)
    libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x76d5c000)
    librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0x76d45000)
    libcrypt.so.1 => /lib/arm-linux-gnueabihf/libcrypt.so.1 (0x76d05000)
    /lib/ld-linux-armhf.so.3 (0x54abc000)
    
    1 回复  |  直到 7 年前
        1
  •  3
  •   Adam Benson    7 年前

    归根结底是装饰的名字。C++编译器不仅仅将函数名放在对象文件中,它还根据函数的定义(尤其是其参数)向名称中添加信息。

    从…起 https://msdn.microsoft.com/en-us/library/56h2zst2.aspx

    表示C和C++程序中的函数、数据和对象 编译对象、数据、, 或函数定义。它记录了调用约定、类型、, 名称装饰,也称为名称损坏,帮助链接器查找

    但是 编译的C代码并没有做到这一点——名称修饰(或名称损坏)是C++自带的。

    为此,请使用以下属性:

    [DllImport("TestDll.dll", EntryPoint="myproc", ExactSpelling=false,CallingConvention=CallingConvention.Cdec‌​l)]
    

    “CallingConvention”位表示“函数是C函数。”

    “Cdecl”的意思是“C声明”,如果我没记错的话。

    更多信息请访问: http://www.codeguru.com/csharp/csharp/cs_data/article.php/c4217/Calling-Unmanaged-Code-Part-1--simple-DLLImport.htm