码迷,mamicode.com
首页 > Web开发 > 详细

.netcore在linux下使用P/invoke方式调用linux动态库

时间:2018-07-03 01:01:27      阅读:2579      评论:0      收藏:0      [点我收藏+]

标签:动态库   linu   cal   res   nat   oba   private   .so   -name   

.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)]
View Code

正常情况下,都是可以调用成功的

如果出现调用失败的情况,可能是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.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_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             else
44                 Console.WriteLine($"调用dlopen打开{libName}失败");
45 
46             var sumPtr = UnixGetProcAddress(libPtr, "sum");
47 
48             if (sumPtr != IntPtr.Zero)
49                 Console.WriteLine($"dlopen调用sum成功");
50             else
51                 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             else
73                 Console.WriteLine($"打开{libname2}失败");
74         }
75     }
View Code

 

.netcore在linux下使用P/invoke方式调用linux动态库

标签:动态库   linu   cal   res   nat   oba   private   .so   -name   

原文地址:https://www.cnblogs.com/twinhead/p/9256518.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!