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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/likang6/article/details/52191606

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




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

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);
        }
    
    }
}







展开阅读全文

没有更多推荐了,返回首页