在C#上从dll调用C函数时出现AccessViolationException

时间:2013-07-03 22:48:39

标签: c# dll access-violation calling-convention cdecl

我正在尝试使用PInvoke来从C dll调用非托管函数。由于dll的源代码无法发布给开发人员,因此其中一些人使用以下声明在Delphi中调用了该函数。我们将SAT.dll与CDECL调用约定一起使用。

function AssociarAssinatura( numeroSessao : Longint; codigoDeAtivacao: PChar; 
               CNPJvalue : PChar; assinaturaCNPJs : PChar ) : PChar ; 
               cdecl; External 'SAT.DLL'; 

基于该结构,我在C#中创建了以下控制台应用程序,以便从同一个DLL测试相同的函数。我做了一些研究,发现delphi中的Longint等价于C#中的int,相当于PChar是指向字符串的指针(但是我使用了C#的字符串)。

class Program
{
    [DllImport("SAT.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern string AssociarAssinatura(int numeroSessao, 
        string codigoDeAtivacao, string CNPJvalue, string assinaturaCNPJs);

    static void Main(string[] args)
    {
        Console.WriteLine("Comienza");
        int numeroSessao = 111111;
        string codigoDeAtivacao = "123123123";
        string cnpJvalue = "2222222222222211111111111111";
        string assinaturaCnpJs = "lrafwegmqcgvpzpbdmcmcgdvf";
        string resposta = AssociarAssinatura(numeroSessao, codigoDeAtivacao, 
                 cnpJvalue, assinaturaCnpJs);

        Console.WriteLine(resposta);

    }
}

当我调用该函数时,抛出AccesViolationException。 AssociarAssinatura的代码有一些内部打印,表明该函数的代码确实运行良好。由于这个原因,我想当函数返回它的值时问题是相关的。我最好的猜测是,我遇到了调用约定的问题。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

此处的问题很可能与您在Delphi中的PChar类型有关。在C#中,默认情况下字符串是Unicode,并且在调用func时,实际上会有从PCharPWideChar的转换,这意味着将分配一个新的内存块来保存这个新的{ {1}}。在.NET和Delphi中如何处理字符串之间的这种互操作和差异很可能导致您的PWideChar

您可以使用AccessViolationException属性明确告诉.NET如何处理特定类型:

MarshalAs

将明确指定字符串的处理方式。在那之后,你的代码应该没问题。