分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

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

发布时间:2023-09-06 02:02责任编辑:赖小花关键词:暂无标签

.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.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 ????}
View Code

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

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

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved