在C#中获取并复用C动态库返回的服务器句柄
C#与Linux动态库交互:正确存储和传递服务器句柄
你的核心问题是用object存储句柄类型不匹配,C语言返回的服务器句柄本质是指针(通常是void*),对应C#里的IntPtr类型,而非object。下面是修正后的实现方案:
1. 修正P/Invoke函数声明
把SendCommand的第一个参数从object改为IntPtr,保证类型和动态库的函数签名完全匹配:
[DllImport("server_connect.so", EntryPoint = "fnConnect", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern IntPtr fnConnect(); [DllImport("server_connect.so", EntryPoint = "fnSendCommand", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void fnSendCommand(IntPtr serverHandle, string command);
2. 安全存储与传递句柄
方案一:封装为类(推荐)
把连接逻辑、句柄存储、命令发送封装到类中,避免外部直接操作句柄,同时增加有效性校验:
public class ServerConnector { private IntPtr _serverHandle = IntPtr.Zero; // 内部声明P/Invoke函数 [DllImport("server_connect.so", EntryPoint = "fnConnect", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] private static extern IntPtr fnConnect(); [DllImport("server_connect.so", EntryPoint = "fnSendCommand", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] private static extern void fnSendCommand(IntPtr serverHandle, string command); /// <summary> /// 建立服务器连接 /// </summary> /// <returns>是否连接成功</returns> public bool Connect() { _serverHandle = fnConnect(); // 根据动态库规则判断句柄是否有效,一般用IntPtr.Zero表示无效 return _serverHandle != IntPtr.Zero; } /// <summary> /// 发送命令到服务器 /// </summary> /// <param name="command">命令内容</param> /// <exception cref="InvalidOperationException">未建立有效连接时抛出</exception> public void SendCommand(string command) { if (_serverHandle == IntPtr.Zero) { throw new InvalidOperationException("请先调用Connect建立服务器连接"); } fnSendCommand(_serverHandle, command); } // 可选:添加断开连接方法(如果动态库提供fnDisconnect函数) // public void Disconnect() // { // if (_serverHandle != IntPtr.Zero) // { // // 调用动态库的断开函数 // // fnDisconnect(_serverHandle); // _serverHandle = IntPtr.Zero; // } // } }
使用方式:
var connector = new ServerConnector(); if (connector.Connect()) { connector.SendCommand("your_command_here"); }
方案二:直接使用IntPtr存储(简单场景)
如果不需要封装类,可以直接用IntPtr存储句柄,在后续调用时传入:
// 建立连接并获取句柄 IntPtr serverHandle = fnConnect(); // 校验句柄有效性后发送命令 if (serverHandle != IntPtr.Zero) { fnSendCommand(serverHandle, "your_command_here"); }
关键说明
IntPtr是C#专门用于表示非托管指针/句柄的类型,和C语言的void*完全对应,避免object带来的类型装箱、拆箱和潜在的类型错误。- 无论哪种方案,都要在使用句柄前校验其有效性(比如判断是否等于
IntPtr.Zero),防止调用无效句柄导致的崩溃。
内容的提问来源于stack exchange,提问作者nlv
相关产品推荐
相关产品推荐

