本文主要是介绍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
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Runtime.InteropServices;
- using System.Windows.Forms;
- using System.Runtime.InteropServices;
- namespace CSharpDemo
- {
- class Program
- {
- [DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]
- public static extern IntPtr LoadLibrary(
- [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
- [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true)]
- public static extern IntPtr GetProcAddress(IntPtr hModule,
- [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
- [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
- public static extern bool FreeLibrary(IntPtr hModule);
- public delegate int InitPrinterManager();
- public delegate void _onMessage_func(IntPtr str);
- public delegate void SetRecvDataCallback(_onMessage_func callback);
- public delegate int SendMessage(byte[] str);
- public delegate int ClosePrinterManager();
- public static IntPtr hLib;
- public static SendMessage sendMessage;
- 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);
- }
- static void WebSocket()
- {
- string str = "{\"cmd\":\"print\",\"requestID\":\"123458976\",\"version\":\"1.0\"}";
- byte[] b = System.Text.Encoding.UTF8.GetBytes(str);
- //用于接口返回
- int Res = -1;
- //IntPtr hLib;
- //以下动态载入dll库
- if (hLib == IntPtr.Zero)
- {
- if (IntPtr.Size == 8) //判断版本号
- hLib = LoadLibrary("PrinterManager64.dll");
- else
- hLib = LoadLibrary("PrinterManager32.dll");
- if (hLib == IntPtr.Zero)
- {
- Console.WriteLine("loadlibrary failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- //以下载入初始化函数initPrinterManager
- IntPtr hapi = GetProcAddress(hLib, "initPrinterManager");
- if (hapi == IntPtr.Zero)
- {
- Console.WriteLine("load initPrinterManager failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- //将初始化函数指针封装成委托,并调用
- InitPrinterManager initPrinterManager =
- (InitPrinterManager)Marshal.GetDelegateForFunctionPointer(hapi, typeof(InitPrinterManager));
- Res = initPrinterManager();
- if (Res != 0)
- {
- Console.WriteLine("run initPrinterManager failed! \n");
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- //以下载入设定回调函数的函数,并调用
- IntPtr hapi2 = GetProcAddress(hLib, "setRecvDataCallback");
- if (hapi2 == IntPtr.Zero)
- {
- Console.WriteLine("load setRecvDataCallback failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- }
- SetRecvDataCallback setRecvDataCallback =
- (SetRecvDataCallback)Marshal.GetDelegateForFunctionPointer(hapi2, typeof(SetRecvDataCallback));
- setRecvDataCallback(onMessage);
- IntPtr hapi3 = GetProcAddress(hLib, "sendMessage");
- if (hapi3 == IntPtr.Zero)
- {
- Console.WriteLine("load sendMessage failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- }
- sendMessage =
- (SendMessage)Marshal.GetDelegateForFunctionPointer(hapi3, typeof(SendMessage));
- Res = sendMessage(b);
- if (Res != 0)
- {
- Console.WriteLine("sendMessage failed! \n");
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- System.Threading.Thread.Sleep(1000);
- }
- else
- {
- Res = sendMessage(b);
- if (Res != 0)
- {
- Console.WriteLine("sendMessage failed! \n");
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- System.Threading.Thread.Sleep(1000);
- }
- }
- public void Close()
- {
- int Res = -1;
- //以下载入关闭连接函数,并调用
- IntPtr hapi4 = GetProcAddress(hLib, "closePrinterManager");
- if (hapi4 == IntPtr.Zero)
- {
- Console.WriteLine("load closePrinterManager failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- }
- ClosePrinterManager closePrinterManager =
- (ClosePrinterManager)Marshal.GetDelegateForFunctionPointer(hapi4, typeof(ClosePrinterManager));
- Res = closePrinterManager();
- if (Res != 0)
- {
- Console.WriteLine("closePrinterManager failed! \n");
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- //释放动态链接库
- FreeLibrary(hLib);
- Console.Read();
- }
- }
- }
查找原因发现回调函数需要声明一个静态对象来存储,改成以下之后,可以正常调用
[csharp] view plain copy
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Runtime.InteropServices;
- namespace CSharpDemo
- {
- class CSharpDemo
- {
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate void WriteToConsoleCallback(IntPtr str);
- [DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]
- public static extern IntPtr LoadLibrary(
- [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
- [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true)]
- public static extern IntPtr GetProcAddress(IntPtr hModule,
- [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
- [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
- public static extern bool FreeLibrary(IntPtr hModule);
- public delegate int InitPrinterManager();
- //public delegate void _onMessage_func(IntPtr str);
- //public delegate void SetRecvDataCallback(_onMessage_func callback);
- public delegate void SetRecvDataCallback(WriteToConsoleCallback callback);
- public delegate int SendMessage(byte[] str);
- public delegate int ClosePrinterManager();
- private static WriteToConsoleCallback callback;
- public static string strMessage = "";
- public static IntPtr hLib;
- public static SendMessage sendMessage;
- //回调函数
- 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);
- }
- /// <summary>
- /// 连接
- /// </summary>
- public static void Websocket()
- {
- try
- {
- //以下载入发送数据函数,并发送数据
- string str = "{\"cmd\":\"print\",\"requestID\":\"123458976\",\"version\":\"1.0\"}";
- byte[] b = System.Text.Encoding.UTF8.GetBytes(str);
- //用于接口返回
- int Res = -1;
- //IntPtr hLib;
- //以下动态载入dll库
- if (hLib == IntPtr.Zero)
- {
- if (IntPtr.Size == 8)
- hLib = LoadLibrary("PrinterManager64.dll");
- else
- hLib = LoadLibrary("PrinterManager32.dll");
- if (hLib == IntPtr.Zero)
- {
- Console.WriteLine("loadlibrary failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- //以下载入初始化函数initPrinterManager
- IntPtr hapi = GetProcAddress(hLib, "initPrinterManager");
- if (hapi == IntPtr.Zero)
- {
- Console.WriteLine("load initPrinterManager failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- //将初始化函数指针封装成委托,并调用
- InitPrinterManager initPrinterManager =
- (InitPrinterManager)Marshal.GetDelegateForFunctionPointer(hapi, typeof(InitPrinterManager));
- Res = initPrinterManager();
- if (Res != 0)
- {
- Console.WriteLine("run initPrinterManager failed! \n");
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- //以下载入设定回调函数的函数,并调用
- IntPtr hapi2 = GetProcAddress(hLib, "setRecvDataCallback");
- if (hapi2 == IntPtr.Zero)
- {
- Console.WriteLine("load setRecvDataCallback failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- }
- SetRecvDataCallback setRecvDataCallback =
- (SetRecvDataCallback)Marshal.GetDelegateForFunctionPointer(hapi2, typeof(SetRecvDataCallback));
- //setRecvDataCallback(onMessage);
- //setRecvDataCallback(null);
- callback = new WriteToConsoleCallback(onMessage);
- setRecvDataCallback(callback);
- IntPtr hapi3 = GetProcAddress(hLib, "sendMessage");
- if (hapi3 == IntPtr.Zero)
- {
- Console.WriteLine("load sendMessage failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- }
- sendMessage =
- (SendMessage)Marshal.GetDelegateForFunctionPointer(hapi3, typeof(SendMessage));
- Res = sendMessage(b);
- if (Res != 0)
- {
- Console.WriteLine("sendMessage failed! \n");
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- System.Threading.Thread.Sleep(1000);
- }
- else
- {
- Res = sendMessage(b);
- if (Res != 0)
- {
- Console.WriteLine("sendMessage failed! \n");
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- System.Threading.Thread.Sleep(1000);
- }
- }
- catch (Exception ex)
- {
- }
- }
- /// <summary>
- /// 关闭关闭连接函数
- /// </summary>
- public void Close()
- {
- int Res = -1;
- //以下载入关闭连接函数,并调用
- IntPtr hapi4 = GetProcAddress(hLib, "closePrinterManager");
- if (hapi4 == IntPtr.Zero)
- {
- Console.WriteLine("load closePrinterManager failed! ErrorNuber:" + Marshal.GetLastWin32Error().ToString());
- }
- ClosePrinterManager closePrinterManager =
- (ClosePrinterManager)Marshal.GetDelegateForFunctionPointer(hapi4, typeof(ClosePrinterManager));
- Res = closePrinterManager();
- if (Res != 0)
- {
- Console.WriteLine("closePrinterManager failed! \n");
- System.Threading.Thread.Sleep(2000);
- System.Environment.Exit(-1);
- }
- //释放动态链接库
- FreeLibrary(hLib);
- }
- }
- }
这篇关于c#调用C++ dll 报未将对象引用到设置对象的实例 的解决方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!