调用本机C ++方法时,在调试模式(F5)中崩溃

时间:2013-12-11 21:09:13

标签: c# c++ pinvoke debug-mode

我试图通过使用LoadLibrary,GetProcAddress和GetDelegateForFunctionPointer来调用C ++方法。

如果我运行.NET 4.0应用程序(Ctrl + F5),一切正常(在发布和调试中)。但是当我启动调试模式(F5)时,程序在调用C ++方法时崩溃。

.cpp:

#include "PointEntree.h"
#include <stdio.h>
extern "C" __declspec( dllexport ) int Test1(int a)
{
    printf("coucou\n");
    return 0;
}

.h:

extern "C" __declspec( dllexport ) int Test1(int);

.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace NETProgram
{
static class NativeMethods
{
    [DllImport("kernel32.dll")]
    public static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32.dll")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

    [DllImport("kernel32.dll")]
    public static extern bool FreeLibrary(IntPtr hModule);
}

class Program
{      
    delegate int Bambou_Test1(int i);

    static void Main(string[] args)
    {
        IntPtr pDll = NativeMethods.LoadLibrary(@"E:\Dev\C#\ImportC++\Bambou\Release\Bambou.dll");
        IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "Test1");

        Bambou_Test1 method = (Bambou_Test1)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(Bambou_Test1));
        method.Invoke(12);
    }
}
}

如果我使用如下的经典DLL导入,它可以工作,但它不是我想要实现的:

[DllImport(@"E:\Dev\C#\ImportC++\Bambou\Debug\Bambou.dll", EntryPoint = "Test1",  CallingConvention=CallingConvention.Cdecl)]
public static extern int Test1(int a);

如果有人有任何想法,那就太棒了!

1 个答案:

答案 0 :(得分:4)

P / Invoke主要用于与Windows API互操作,因此默认情况下使用StdCall约定。 C默认使用Cdecl约定。您需要更改两侧以明确指定调用约定,以便它在两侧都匹配。

您的经典DLL导入使用[DllImport(..., CallingConvention=CallingConvention.Cdecl)指定约定,基于GetDelegateForFunctionPointer的变体未指定调用约定(因此使用StdCall)。您需要使用[UnmanagedFunctionPointer(CallingConvention.Cdecl)]指定它。

如果没有附加调试器,您的代码就是错误的,它只是隐藏了错误。通常这种不匹配会导致堆栈指针失去平衡,导致即时崩溃,但.net编组代码似乎对堆栈指针有特殊处理,以避免崩溃。如果没有调试器,则会默默地吞下错误,并使用调试器显示错误。