c#调用C++ dll 报未将对象引用到设置对象的实例 的解决方案


PS: 我遇到的问题和这个情况类似。


提炼核心语句:


public delegate void WriteToConsoleCallback(IntPtr str); 

private static WriteToConsoleCallback callback; 

callback = new WriteToConsoleCallback(onMessage);  
setRecvDataCallback(callback);   //setRecvDataCallback 是DLL导出函数

static void onMessage(IntPtr str)  
{  
    byte[] buffer1 = Encoding.Default.GetBytes(Marshal.PtrToStringAnsi(str));  
    byte[] buffer2 = Encoding.Convert(Encoding.UTF8, Encoding.Default, buffer1, 0, buffer1.Length);  
    string strBuffer = Encoding.Default.GetString(buffer2, 0, buffer2.Length);  
}  




来源:http://blog.csdn.net/likang6/article/details/52191606


c# 调用 C++ dll 第一次调用的时候,可以正常加载正常返回,多次调用之后在执行完 sendMessage(b); 之后,就会报 未将对象引用到设置对象的实例,代码如下

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Runtime.InteropServices;  
  5. using System.Windows.Forms;  
  6. using System.Runtime.InteropServices;  
  7.   
  8. namespace CSharpDemo  
  9. {  
  10.     class Program  
  11.     {  
  12.         [DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]  
  13.         public static extern IntPtr LoadLibrary(  
  14.            [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);  
  15.   
  16.         [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true)]  
  17.         public static extern IntPtr GetProcAddress(IntPtr hModule,  
  18.                    [MarshalAs(UnmanagedType.LPStr)] string lpProcName);  
  19.   
  20.         [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]  
  21.         public static extern bool FreeLibrary(IntPtr hModule);  
  22.   
  23.   
  24.         public delegate int InitPrinterManager();  
  25.         public delegate void _onMessage_func(IntPtr str);  
  26.         public delegate void SetRecvDataCallback(_onMessage_func callback);  
  27.         public delegate int SendMessage(byte[] str);  
  28.         public delegate int ClosePrinterManager();  
  29.   
  30.         public static IntPtr hLib;  
  31.         public static SendMessage sendMessage;  
  32.         static void onMessage(IntPtr str)  
  33.         {  
  34.   
  35.             byte[] buffer1 = Encoding.Default.GetBytes(Marshal.PtrToStringAnsi(str));  
  36.             byte[] buffer2 = Encoding.Convert(Encoding.UTF8, Encoding.Default, buffer1, 0, buffer1.Length);  
  37.             string strBuffer = Encoding.Default.GetString(buffer2, 0, buffer2.Length);  
  38.   
  39.   
  40.         }  
  41.         static void WebSocket()  
  42.         {  
  43.   
  44.   
  45.             string str = "{\"cmd\":\"print\",\"requestID\":\"123458976\",\"version\":\"1.0\"}";  
  46.   
  47.             byte[] b = System.Text.Encoding.UTF8.GetBytes(str);  
  48.   
  49.   
  50.             //用于接口返回  
  51.             int Res = -1;  
  52.             //IntPtr hLib;  
  53.             //以下动态载入dll库  
  54.             if (hLib == IntPtr.Zero)  
  55.             {  
  56.                 if (IntPtr.Size == 8)  //判断版本号  
  57.                     hLib = LoadLibrary("PrinterManager64.dll");  
  58.                 else  
  59.                     hLib = LoadLibrary("PrinterManager32.dll");  
  60.   
  61.   
  62.                 if (hLib == IntPtr.Zero)  
  63.                 {  
  64.   
  65.                     Console.WriteLine("loadlibrary failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  66.                     System.Threading.Thread.Sleep(2000);  
  67.                     System.Environment.Exit(-1);  
  68.                 }  
  69.                 //以下载入初始化函数initPrinterManager  
  70.                 IntPtr hapi = GetProcAddress(hLib, "initPrinterManager");  
  71.                 if (hapi == IntPtr.Zero)  
  72.                 {  
  73.                     Console.WriteLine("load initPrinterManager failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  74.                     System.Threading.Thread.Sleep(2000);  
  75.                     System.Environment.Exit(-1);  
  76.                 }  
  77.                 //将初始化函数指针封装成委托,并调用  
  78.                 InitPrinterManager initPrinterManager =  
  79.                     (InitPrinterManager)Marshal.GetDelegateForFunctionPointer(hapi, typeof(InitPrinterManager));  
  80.                 Res = initPrinterManager();  
  81.                 if (Res != 0)  
  82.                 {  
  83.                     Console.WriteLine("run initPrinterManager failed! \n");  
  84.                     System.Threading.Thread.Sleep(2000);  
  85.                     System.Environment.Exit(-1);  
  86.                 }  
  87.   
  88.                 //以下载入设定回调函数的函数,并调用  
  89.                 IntPtr hapi2 = GetProcAddress(hLib, "setRecvDataCallback");  
  90.                 if (hapi2 == IntPtr.Zero)  
  91.                 {  
  92.                     Console.WriteLine("load setRecvDataCallback failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  93.                 }  
  94.                 SetRecvDataCallback setRecvDataCallback =  
  95.                     (SetRecvDataCallback)Marshal.GetDelegateForFunctionPointer(hapi2, typeof(SetRecvDataCallback));  
  96.                 setRecvDataCallback(onMessage);  
  97.   
  98.                 IntPtr hapi3 = GetProcAddress(hLib, "sendMessage");  
  99.   
  100.   
  101.                 if (hapi3 == IntPtr.Zero)  
  102.                 {  
  103.                     Console.WriteLine("load sendMessage failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  104.                 }  
  105.                 sendMessage =  
  106.                    (SendMessage)Marshal.GetDelegateForFunctionPointer(hapi3, typeof(SendMessage));  
  107.                 Res = sendMessage(b);  
  108.                 if (Res != 0)  
  109.                 {  
  110.                     Console.WriteLine("sendMessage failed! \n");  
  111.                     System.Threading.Thread.Sleep(2000);  
  112.                     System.Environment.Exit(-1);  
  113.                 }  
  114.                 System.Threading.Thread.Sleep(1000);  
  115.             }  
  116.             else  
  117.             {  
  118.                 Res = sendMessage(b);  
  119.                 if (Res != 0)  
  120.                 {  
  121.                     Console.WriteLine("sendMessage failed! \n");  
  122.                     System.Threading.Thread.Sleep(2000);  
  123.                     System.Environment.Exit(-1);  
  124.                 }  
  125.                 System.Threading.Thread.Sleep(1000);  
  126.             }  
  127.   
  128.   
  129.   
  130.         }  
  131.       
  132.   
  133.          
  134.   
  135.   
  136.         public void Close()  
  137.         {  
  138.             int Res = -1;  
  139.             //以下载入关闭连接函数,并调用  
  140.             IntPtr hapi4 = GetProcAddress(hLib, "closePrinterManager");  
  141.             if (hapi4 == IntPtr.Zero)  
  142.             {  
  143.                 Console.WriteLine("load closePrinterManager failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  144.             }  
  145.             ClosePrinterManager closePrinterManager =  
  146.                 (ClosePrinterManager)Marshal.GetDelegateForFunctionPointer(hapi4, typeof(ClosePrinterManager));  
  147.             Res = closePrinterManager();  
  148.             if (Res != 0)  
  149.             {  
  150.                 Console.WriteLine("closePrinterManager failed! \n");  
  151.                 System.Threading.Thread.Sleep(2000);  
  152.                 System.Environment.Exit(-1);  
  153.             }  
  154.             //释放动态链接库  
  155.             FreeLibrary(hLib);  
  156.             Console.Read();  
  157.         }  
  158.     }  
  159. }  




查找原因发现回调函数需要声明一个静态对象来存储,改成以下之后,可以正常调用

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Runtime.InteropServices;  
  5.   
  6. namespace CSharpDemo  
  7. {  
  8.     class CSharpDemo  
  9.     {  
  10.         [UnmanagedFunctionPointer(CallingConvention.StdCall)]  
  11.         public delegate void WriteToConsoleCallback(IntPtr str);  
  12.   
  13.         [DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]  
  14.         public static extern IntPtr LoadLibrary(  
  15.            [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);  
  16.   
  17.         [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true)]  
  18.         public static extern IntPtr GetProcAddress(IntPtr hModule,  
  19.                    [MarshalAs(UnmanagedType.LPStr)] string lpProcName);  
  20.   
  21.         [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]  
  22.         public static extern bool FreeLibrary(IntPtr hModule);  
  23.   
  24.         public delegate int InitPrinterManager();  
  25.         //public delegate void _onMessage_func(IntPtr str);  
  26.         //public delegate void SetRecvDataCallback(_onMessage_func callback);  
  27.         public delegate void SetRecvDataCallback(WriteToConsoleCallback callback);  
  28.         public delegate int SendMessage(byte[] str);  
  29.         public delegate int ClosePrinterManager();  
  30.         private static WriteToConsoleCallback callback;  
  31.   
  32.         public static string strMessage = "";  
  33.         public static IntPtr hLib;  
  34.         public static SendMessage sendMessage;  
  35.         //回调函数  
  36.         static void onMessage(IntPtr str)  
  37.         {  
  38.   
  39.             byte[] buffer1 = Encoding.Default.GetBytes(Marshal.PtrToStringAnsi(str));  
  40.             byte[] buffer2 = Encoding.Convert(Encoding.UTF8, Encoding.Default, buffer1, 0, buffer1.Length);  
  41.             string strBuffer = Encoding.Default.GetString(buffer2, 0, buffer2.Length);  
  42.   
  43.         }  
  44.         /// <summary>  
  45.         /// 连接  
  46.         /// </summary>  
  47.         public static void Websocket()  
  48.         {  
  49.             try  
  50.             {  
  51.                 //以下载入发送数据函数,并发送数据  
  52.                 string str = "{\"cmd\":\"print\",\"requestID\":\"123458976\",\"version\":\"1.0\"}";  
  53.                 byte[] b = System.Text.Encoding.UTF8.GetBytes(str);  
  54.   
  55.   
  56.                 //用于接口返回  
  57.                 int Res = -1;  
  58.                 //IntPtr hLib;  
  59.                 //以下动态载入dll库  
  60.                 if (hLib == IntPtr.Zero)  
  61.                 {  
  62.                     if (IntPtr.Size == 8)  
  63.                         hLib = LoadLibrary("PrinterManager64.dll");  
  64.                     else  
  65.                         hLib = LoadLibrary("PrinterManager32.dll");  
  66.   
  67.   
  68.                     if (hLib == IntPtr.Zero)  
  69.                     {  
  70.   
  71.                         Console.WriteLine("loadlibrary failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  72.                         System.Threading.Thread.Sleep(2000);  
  73.                         System.Environment.Exit(-1);  
  74.                     }  
  75.                     //以下载入初始化函数initPrinterManager  
  76.                     IntPtr hapi = GetProcAddress(hLib, "initPrinterManager");  
  77.                     if (hapi == IntPtr.Zero)  
  78.                     {  
  79.                         Console.WriteLine("load initPrinterManager failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  80.                         System.Threading.Thread.Sleep(2000);  
  81.                         System.Environment.Exit(-1);  
  82.                     }  
  83.                     //将初始化函数指针封装成委托,并调用  
  84.                     InitPrinterManager initPrinterManager =  
  85.                         (InitPrinterManager)Marshal.GetDelegateForFunctionPointer(hapi, typeof(InitPrinterManager));  
  86.                     Res = initPrinterManager();  
  87.                     if (Res != 0)  
  88.                     {  
  89.                         Console.WriteLine("run initPrinterManager failed! \n");  
  90.                         System.Threading.Thread.Sleep(2000);  
  91.                         System.Environment.Exit(-1);  
  92.                     }  
  93.   
  94.                     //以下载入设定回调函数的函数,并调用  
  95.                     IntPtr hapi2 = GetProcAddress(hLib, "setRecvDataCallback");  
  96.                     if (hapi2 == IntPtr.Zero)  
  97.                     {  
  98.                         Console.WriteLine("load setRecvDataCallback failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  99.                     }  
  100.                     SetRecvDataCallback setRecvDataCallback =  
  101.                         (SetRecvDataCallback)Marshal.GetDelegateForFunctionPointer(hapi2, typeof(SetRecvDataCallback));  
  102.                     //setRecvDataCallback(onMessage);  
  103.                     //setRecvDataCallback(null);  
  104.                     callback = new WriteToConsoleCallback(onMessage);  
  105.                     setRecvDataCallback(callback);  
  106.   
  107.                     IntPtr hapi3 = GetProcAddress(hLib, "sendMessage");  
  108.   
  109.   
  110.                     if (hapi3 == IntPtr.Zero)  
  111.                     {  
  112.                         Console.WriteLine("load sendMessage failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  113.                     }  
  114.                     sendMessage =  
  115.                        (SendMessage)Marshal.GetDelegateForFunctionPointer(hapi3, typeof(SendMessage));  
  116.                     Res = sendMessage(b);  
  117.                     if (Res != 0)  
  118.                     {  
  119.                         Console.WriteLine("sendMessage failed! \n");  
  120.                         System.Threading.Thread.Sleep(2000);  
  121.                         System.Environment.Exit(-1);  
  122.                     }  
  123.   
  124.                     System.Threading.Thread.Sleep(1000);  
  125.                 }  
  126.                 else  
  127.                 {  
  128.   
  129.                     Res = sendMessage(b);  
  130.                     if (Res != 0)  
  131.                     {  
  132.                         Console.WriteLine("sendMessage failed! \n");  
  133.                         System.Threading.Thread.Sleep(2000);  
  134.                         System.Environment.Exit(-1);  
  135.                     }  
  136.                     System.Threading.Thread.Sleep(1000);  
  137.                 }  
  138.             }  
  139.             catch (Exception ex)  
  140.             {  
  141.   
  142.             }  
  143.         }  
  144.         /// <summary>  
  145.         /// 关闭关闭连接函数  
  146.         /// </summary>  
  147.         public void Close()  
  148.         {  
  149.             int Res = -1;  
  150.             //以下载入关闭连接函数,并调用  
  151.             IntPtr hapi4 = GetProcAddress(hLib, "closePrinterManager");  
  152.             if (hapi4 == IntPtr.Zero)  
  153.             {  
  154.                 Console.WriteLine("load closePrinterManager failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());  
  155.             }  
  156.             ClosePrinterManager closePrinterManager =  
  157.                 (ClosePrinterManager)Marshal.GetDelegateForFunctionPointer(hapi4, typeof(ClosePrinterManager));  
  158.             Res = closePrinterManager();  
  159.             if (Res != 0)  
  160.             {  
  161.                 Console.WriteLine("closePrinterManager failed! \n");  
  162.                 System.Threading.Thread.Sleep(2000);  
  163.                 System.Environment.Exit(-1);  
  164.             }  
  165.             //释放动态链接库  
  166.             FreeLibrary(hLib);  
  167.         }  
  168.       
  169.     }  
  170. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值