C# .net核心-PInvoke C共享库函数,它依赖于另一个共享库

C# .net核心-PInvoke C共享库函数,它依赖于另一个共享库,c#,raspberry-pi,shared-libraries,.net-core,pinvoke,C#,Raspberry Pi,Shared Libraries,.net Core,Pinvoke,我为现有库()编写了一些包装器代码来读取温度传感器,但在使用该库时出现了一个错误 我的包装库看起来像: mylib.h \ifndef mylib\h__ #定义mylib_h__ 外部空隙读取传感器(); #恩迪夫 mylib.c #包括“mylib.h” #包括 无效读_传感器(){ //这是对wiringPi库的第一个调用 如果(wiringPiSetup()=-1) 出口(1); ... } 然后我使用gcc编译我的库: gcc-Wall-Werror-fPIC-cmylib.c g

我为现有库()编写了一些包装器代码来读取温度传感器,但在使用该库时出现了一个错误

我的包装库看起来像:

mylib.h
\ifndef mylib\h__
#定义mylib_h__
外部空隙读取传感器();
#恩迪夫
mylib.c
#包括“mylib.h”
#包括
无效读_传感器(){
//这是对wiringPi库的第一个调用
如果(wiringPiSetup()=-1)
出口(1);
...
}
然后我使用gcc编译我的库:

gcc-Wall-Werror-fPIC-cmylib.c
gcc-shared-o libmylib.so mylib.o-lwiringPi
cp libmylib.so/usr/lib/
提示:如果此库的C程序使用正常,则一切正常

现在有了我的C#程序,它使用
PInvoke
从这个库调用
read_sensor()

Program.cs
类程序
{
[DllImport(“wiringPi”)]
静态外部输入wiringPiSetup();
[DllImport(“mylib”)]
静态外部空隙读取传感器();
静态void Main(字符串[]参数)
{
wiringPiSetup();
读取传感器();
}
}
此程序使用以下参数编译:

dontet publish -r linux-arm
抄写到我的树莓皮上

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

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

这里怎么了

我的第一个想法是,我的程序不知道wiringPi库。因此,我为这个dll添加了一个导出,并调用
wiringPiSetup()
进行测试。无论是否使用此语句,结果都相同

我还在自定义库中添加了一个没有wiringPi依赖项的测试函数。这被C#称为罚款

我当时是不是把事情搞砸了

编辑:

命令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)

归根结底,这就是所谓的装饰。C++编译器不只是把函数的名字放在对象文件中,而是根据函数的定义(最明显的是它的参数)将信息添加到名称。 从

C和C++程序中的函数、数据和对象表示 内部由他们的名字装饰。修饰的名称是一个编码的名称 编译器在编译对象、数据、, 或函数定义。它记录调用约定、类型, 函数参数和其他信息以及名称。这 名称装饰,也称为名称损坏,帮助链接器查找 链接可执行文件时正确的函数和对象

<> >但编译的C++代码不这样做。 因此,您必须告诉C#“此函数的名称没有修饰。”

为此,请使用如下属性:

[DllImport("TestDll.dll", EntryPoint="myproc", ExactSpelling=false,CallingConvention=CallingConvention.Cdec‌​l)]
“调用约定”位表示“函数是C函数。”

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


有关更多信息,请访问:

您是否已经问过这个问题?请注意中的LD_DEBUG用法,以获取更多疑难解答信息。
ldd/usr/lib/libmylib。那么
怎么说?它是否包含一个
libwiringPi.so
?我将输出添加到我的问题中。名称装饰?类似于此工作:[DllImport(“TestDll.dll”,EntryPoint=“myproc”,ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]