从C#上的dll调用C函数时发生AccessViolationException

本文关键字:AccessViolationException 函数 上的 dll 调用 | 更新日期: 2023-09-27 18:20:58

我正试图使用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的代码有一些内部印记,表明该函数的代码确实运行良好。因此,我想当函数返回其值时,问题是相关的。我的最佳猜测是,不知何故,我对电话会议有意见。有什么想法吗?

从C#上的dll调用C函数时发生AccessViolationException

您的问题很可能与Delphi中的PChar类型有关。在C#中,字符串默认为Unicode,当调用func时,实际上会有一个从PCharPWideChar的转换,这意味着将分配一个新的内存块来容纳这个新的PWideChar。.NET和Delphi中处理字符串的方式之间的这种互操作和差异很可能导致AccessViolationException

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

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

它将明确指定如何处理字符串。在那之后,您的代码应该是好的。