使用 DLLImport 函数时程序崩溃

Posted

技术标签:

【中文标题】使用 DLLImport 函数时程序崩溃【英文标题】:Program crash when using DLLImport function 【发布时间】:2019-07-03 14:32:55 【问题描述】:

我正在尝试使用 C++ dll 中的一个函数来设置回调,以便将来可以在程序中使用,但是当我调用该函数时,应用程序崩溃而不显示错误或任何内容。

C#代码:


        [DllImport("DocProc.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern ulong DPSetCallBacks(DPHandle hdl, IntPtr cbs);

        public delegate void ConnectedCB(DPHandle hdl);
        public delegate void DisconnectedCB(DPHandle hdl);
        public delegate void DocCompleteCB(DPHandle hdl);
        public delegate void DocImageCompleteCB(DPHandle hdl);
        public delegate void DocImageSnippetCompleteCB(DPHandle hdl);
        public delegate void DocReadCompleteCB(DPHandle hdl);
        public delegate void ExceptionCompleteCB(DPHandle hdl);
        public delegate void ExceptionInProgressCB(DPHandle hdl);
        public delegate void FlowStoppedCB(DPHandle hdl);
        public delegate void HopperEmptyCB(DPHandle hdl);
        public delegate void IdleCB(DPHandle hdl);
        public delegate void MachineDeadCB(DPHandle hdl);
        public delegate void PoweredDownCB(DPHandle hdl);
        public delegate void PoweredUpCB(DPHandle hdl);
        public delegate void PoweringUpCB(DPHandle hdl);
        public delegate void ReadyingCB(DPHandle hdl);
        public delegate void ReadyToProcessCB(DPHandle hdl);
        public delegate void StateExceptionCB(DPHandle hdl);
        public delegate void WarningCB(DPHandle hdl);
        public delegate void NvmReadCompleteCB(DPHandle hdl);
        public delegate void MakeReadyToFlowCompleteCB(DPHandle hdl);

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
        public struct DPcbs
        
            public int size;
            public ConnectedCB connectedCB;
            public DisconnectedCB disconnectedCB;
            public DocCompleteCB docCompleteCB;
            public DocImageCompleteCB docImageComplete;
            public DocImageSnippetCompleteCB docImageSnippetCompleteCB;
            public DocReadCompleteCB docReadComplete;
            public ExceptionCompleteCB exceptionCompleteCB;
            public ExceptionInProgressCB exceptionInProgressCB;
            public FlowStoppedCB flowStoppedCB;
            public HopperEmptyCB hopperEmptyCB;
            public IdleCB idleCB;
            public MachineDeadCB machineDeadCB;
            public PoweredDownCB poweredDownCB;
            public PoweredUpCB poweredUpCB;
            public PoweringUpCB poweringUpCB;
            public ReadyingCB readyingCB;
            public ReadyToProcessCB readyToProcessCB;
            public StateExceptionCB stateExceptionCB;
            public WarningCB warningCB;
            public NvmReadCompleteCB nvmReadCompleteCB;
            public MakeReadyToFlowCompleteCB makeReadyToFlowCompleteCB;
        

C++ 代码:

typedef struct  
unsigned int size;
 ConnectedCB connectedCB;
 DisconnectedCB disconnectedCB;
 DocCompleteCB docCompleteCB;
 DocImageCompleteCB docImageComplete;
 DocImageSnippetCompleteCB docImageSnippetCompleteCB;
 DocReadCompleteCB docReadComplete;
 ExceptionCompleteCB exceptionCompleteCB;
 ExceptionInProgressCB exceptionInProgressCB;
 FlowStoppedCB flowStoppedCB;
 HopperEmptyCB hopperEmptyCB;
 IdleCB idleCB;
 MachineDeadCB machineDeadCB;
 PoweredDownCB poweredDownCB;
 PoweredUpCB poweredUpCB;
 PoweringUpCB poweringUpCB;
 ReadyingCB readyingCB;
 ReadyToProcessCB readyToProcessCB;
 StateExceptionCB stateExceptionCB;
 WarningCB warningCB; 
 NvmReadCompleteCB nvmReadCompleteCB;
 MakeReadyToFlowCompleteCB makeReadyToFlowCompleteCB;


unsigned long DPSetCallBacks(DPHandle hdl, DPcbs *dpcbs);

我是这样使用的:

 DPcbs cbs = new DPcbs();
               cbs.poweredUpCB = PoweredUp;

                ptr = Marshal.AllocHGlobal(Marshal.SizeOf(cbs));
                try
                

                    // Copy the struct to unmanaged memory.
                    Marshal.StructureToPtr(cbs, ptr, false);

                    DPSetCallBacks(handle, ptr);

                
                finally
                
                    // Free the unmanaged memory.
                    Marshal.FreeHGlobal(ptr);
                

结果是应用程序崩溃而没有任何可见的错误。任何帮助将不胜感激。提前致谢!

【问题讨论】:

如果没有错误,你的意思是它崩溃了?我没有看到您正在执行任何类型输出的任何代码,所以它不能成功完成吗?你的意思是控制台窗口正在关闭?在 C# 程序的末尾添加 Console.ReadLine() 这是一个 Windows 窗体应用程序,只要运行该函数,应用程序就会退出。 垃圾收集器可能以某种方式运行,当从托管代码调用时,您的托管指针消失了。可能与此重复:***.com/questions/4906931/… 嗯,这与我正在做的事情有点不同...... C# ulong 是 64 位,C++ unsigned long 是 32 位。缺少大量关键代码部分,这可能是问题的原因。我们不知道调用约定是否匹配,代理是否受到保护以防收集,此外可能还有更多潜在的陷阱。不幸的是,pinvoke 问题缺少关键细节是很常见的。 【参考方案1】:

如果您想在 DLL 中编译此类 C++ 代码,最好将其包含在类中并提供访问器方法。

如果不包装,c# 项目永远无法访问已编译的 typedef 结构!

注意您的运行时编译的 DLL 版本

【讨论】:

我真的不明白你的意思,你能澄清一下吗?谢谢。 那么,这究竟是如何回答这个问题的呢?

以上是关于使用 DLLImport 函数时程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用挂钩函数时应用程序崩溃

调用OpenGL函数时程序崩溃

尝试使用引用 C 的函数写入文件时程序崩溃

为啥不在应用程序崩溃时启动外部崩溃转储处理程序?

在函数中使用多个inout参数时应用程序崩溃

dataSnapshot 函数不起作用 - 函数调用时应用程序崩溃