从C#到C ++非托管代码的多个函数调用导致AccessViolationException

时间:2012-01-04 20:29:20

标签: c# interop pinvoke marshalling unmanaged

我在C#程序中声明了一个DLL导入,如下所示:

[DllImport("C:\\c_keycode.dll", EntryPoint = "generateKeyCode", 
           CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr generateKeyCode(char[] serial, char[] option, char c_type);

它引用了我的DLL内部的函数generateKeyCode()

以下是导致错误的代码(使用的断点):

const char* generateKeyCode(char serial[], 
                 char option[], 
                 char c_type)
{
returnBufferString = "";
SHA1_CTX context;
int optionLength = 0;
#ifdef WIN32
unsigned char buffer[16384] = {0};
#else
unsigned char buffer[256] = {0}; 

#endif
//char output[80];
char keycode[OPTION_KEY_LENGTH+1]        = "";
int digest_array_size = 10; //default value for digest array size
unsigned char digest[20] = {0};
char optx[24] = {0};
char c_type_upper;
// Combine serial # and Option or Version number

char str1[30] = {0};
int i;
int size = 0;
int pos = 0;


...
...
}

基本上,我导入了这个DLL,所以我可以传递函数参数,它可以做它的算法,只需返回一个结果。我使用了这个封送功能......

public static string genKeyCode_marshal(string serial, string option, char type)
{
    return Marshal.PtrToStringAnsi(generateKeyCode(serial.ToCharArray(), 
           option.ToCharArray(), type));
}

...所以我可以正常拨打电话。在我的C ++头文件中,我已经定义了一个字符串,正如所指示的那样有助于回答这个question(它是C / C ++函数顶部的returnBufferString变量)。 / p>

当我使用NumericUpDown控件从1.0到9.9以0.1为增量(每次向上或向下伴随另一个函数调用)时,我多次调用此函数,然后再次返回。但是,每次我尝试这样做时,程序会在看似设定数量的函数调用之后挂断(如果我直接上下移动,则在返回的路上停止在1.9,如果我上下移动一下,则停止更早) 。

请注意它有效并且给了我想要的价值,那里没有差异。

我将缓冲区大小更改为更小的数字(5012),当我尝试运行程序时,在第一个函数调用时它抛出了AccessViolationException。然而,将缓冲区大小加倍(32768),与原始缓冲区大小相比没有任何影响 - 从1.0直接上升至9.9并再次向下返回,它停在1.9并抛出异常。

编辑:默认为ANSI,因此它是ANSI。没有问题。这是一个内存分配问题吗?

2 个答案:

答案 0 :(得分:2)

我建议尝试以下方法:

[DllImport("C:\\c_keycode.dll", EntryPoint = "generateKeyCode", 
       CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern IntPtr generateKeyCode(string serial, string option, char c_type);

请注意CharSet属性的新DllImport字段。

下一个想法是明确使用MarshalAs属性:

[DllImport("C:\\c_keycode.dll", EntryPoint = "generateKeyCode", 
       CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
static extern IntPtr generateKeyCode([MarshalAs(UnmanagedType.LPTStr)] string serial, [MarshalAs(UnmanagedType.LPTStr)] string option, char c_type);

答案 1 :(得分:0)

我知道这可能不太令人满意,但是一旦我删除了我用来从我的C / C ++ DLL中调试的输出重定向,问题就停止了。现在一切正常,所以我猜这基本上等同于回答我自己的问题。感谢大家的回复。