.netcore下已经实现了通过p/invoke方式调用linux的动态链接库(*.so)文件
1 [DllImport(@"libdl.so.2")] 2 ????????public static extern IntPtr dlopen(string filename, int flags); 3 ????????[DllImport("libdl.so.2")] 4 ????????public static extern IntPtr dlsym(IntPtr handle, string symbol); 5 ?6 ????????[DllImport("libdl.so.2", EntryPoint = "dlopen")] 7 ????????private static extern IntPtr UnixLoadLibrary(String fileName, int flags); 8 ?9 ????????[DllImport("libdl.so.2", EntryPoint = "dlclose", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]10 ????????private static extern int UnixFreeLibrary(IntPtr handle);11 12 ????????[DllImport("libdl.so.2", EntryPoint = "dlsym", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]13 ????????private static extern IntPtr UnixGetProcAddress(IntPtr handle, String symbol);14 15 ????????[DllImport("libdl.so.2", EntryPoint = "dlerror", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
正常情况下,都是可以调用成功的
如果出现调用失败的情况,可能是so文件缺少了一些依赖文件,可以通过ldd命令进行查看
ldd libzmq.so
如果有某些依赖文件找不到,会出现not found的字样,比如下面这种
/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20‘ not found (required by */3rd-party/protobuf-2.4.1/src/.libs/libprotobuf.so.7)
/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20‘ not found (required by */3rd-party/protobuf-2.4.1/src/.libs/libprotoc.so.7)
可以使用string命令查找是否确实缺少了依赖
strings /usr/lib64/libstdc++.so.6 |grep GLIBCXX 得到结果GLIBCXX_3.4GLIBCXX_3.4.1GLIBCXX_3.4.2GLIBCXX_3.4.3GLIBCXX_3.4.4GLIBCXX_3.4.5GLIBCXX_3.4.6GLIBCXX_3.4.7GLIBCXX_3.4.8GLIBCXX_3.4.9GLIBCXX_3.4.10GLIBCXX_3.4.11GLIBCXX_3.4.12GLIBCXX_3.4.13GLIBCXX_3.4.14GLIBCXX_3.4.15GLIBCXX_3.4.16GLIBCXX_3.4.17GLIBCXX_DEBUG_MESSAGE_LENGTH
确实缺少了文件,这种情况下,我们需要使用find命令来查找依赖文件
find / -name libstdc++.so.6*
如果能找到依赖的so文件,可以使用cp命令将文件复制到lib64目录
cp /usr/local/lib64/libstdc++.so.6.0.20 /usr/lib64 //复制文件
Centos下系统目录是/usr/lib64,Suse下可能系统目录会有不同
如果有旧文件,可以使用rm命令,先删除旧文件
sudo rm -rf /usr/lib64/libstdc++.so.6 ?//删除旧文件
最后在使用ln命令,链接到新文件
sudo ln -s /usr/lib64/libstdc++.so.6.0.20 /usr/lib64/libstdc++.so.6 //链接到新版本
这些都做好之后,旧可以测试dlopen命令是否能正常打开文件了,如果可以正常打开,那dllimport方式就可以正常使用
没有开发dllimport的源码,很怀疑它内部也是调用了linux下的dlopen命令来调用so文件
出了直接使用dllimport方式来调用,还可以使用委托的方式,来调用so文件
下面是测试代码,可以比较完整说明.netcore下p/invoke方式调用so文件
1 public class SoTester 2 ????{ 3 ????????private const string LibraryName = "libzmq"; 4 ?5 ????????const int RTLD_NOW = 2; // for dlopen‘s flags 6 ????????const int RTLD_GLOBAL = 8; 7 ?8 ????????[DllImport(@"libdl.so.2")] 9 ????????public static extern IntPtr dlopen(string filename, int flags);10 ????????[DllImport("libdl.so.2")]11 ????????public static extern IntPtr dlsym(IntPtr handle, string symbol);12 13 ????????[DllImport("libdl.so.2", EntryPoint = "dlopen")]14 ????????private static extern IntPtr UnixLoadLibrary(String fileName, int flags);15 16 ????????[DllImport("libdl.so.2", EntryPoint = "dlclose", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]17 ????????private static extern int UnixFreeLibrary(IntPtr handle);18 19 ????????[DllImport("libdl.so.2", EntryPoint = "dlsym", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]20 ????????private static extern IntPtr UnixGetProcAddress(IntPtr handle, String symbol);21 22 ????????[DllImport("libdl.so.2", EntryPoint = "dlerror", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]23 ????????private static extern IntPtr UnixGetLastError();24 25 ????????public delegate int sumHandler(int a, int b);26 ????????public static sumHandler sumfunc = null;27 28 ????????[DllImport("libNativeLib.so", EntryPoint = "sum", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]29 ????????public static extern int Sum(int a, int b);30 31 ????????public void Start()32 ????????{33 ????????????IntPtr libPtr = IntPtr.Zero;34 35 ????????????string libName = $"{AppContext.BaseDirectory}libNativeLib.so";36 37 ????????????libPtr = UnixLoadLibrary(libName, 2 | 8);38 39 ????????????//libPtr = dlopen(libName, RTLD_NOW);40 41 ????????????if (libPtr != IntPtr.Zero)42 ????????????????Console.WriteLine($"调用dlopen打开{libName}成功");43 ????????????else44 ????????????????Console.WriteLine($"调用dlopen打开{libName}失败");45 46 ????????????var sumPtr = UnixGetProcAddress(libPtr, "sum");47 48 ????????????if (sumPtr != IntPtr.Zero)49 ????????????????Console.WriteLine($"dlopen调用sum成功");50 ????????????else51 ????????????????Console.WriteLine($"dlopen调用sum失败");52 53 ????????????sumfunc = Marshal.GetDelegateForFunctionPointer<sumHandler>(sumPtr);54 55 ????????????int ret = sumfunc(1, 3);56 57 ????????????Console.WriteLine($"调用sum结果:{ret}");58 59 ????????????var sumRet = Sum(5, 7);60 61 ????????????Console.WriteLine($"DllImport调用sum结果:{sumRet}");62 63 ????????????//var libname2 = $"libc.so.6";64 ????????????var libname2 = $"{AppContext.BaseDirectory}libzmq.so";65 ????????????//var libname2 = $"{AppContext.BaseDirectory}libAdminConsole.so";66 ????????????var consolePtr = UnixLoadLibrary(libname2, 2 | 8);67 ????????????var erroPtr = UnixGetLastError();68 ????????????Console.WriteLine($"错误描述:{Marshal.PtrToStringAnsi(erroPtr)}");69 70 ????????????if (consolePtr != IntPtr.Zero)71 ????????????????Console.WriteLine($"打开{libname2}成功");72 ????????????else73 ????????????????Console.WriteLine($"打开{libname2}失败");74 ????????}75 ????}
.netcore在linux下使用P/invoke方式调用linux动态库
原文地址:https://www.cnblogs.com/twinhead/p/9256518.html