0

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

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 的代码有一些内部打印,表明该函数的代码确实运行良好。因此,我猜这个问题与函数返回它的值有关。我最好的猜测是,我在调用约定方面遇到了问题。有什么想法吗?

4

1 回答 1

0

您的问题很可能与您PChar在 Delphi 中的类型有关。在 C# 中,字符串默认是 Unicode,当调用你的 func 时,实际上会有一个从 aPChar到的转换PWideChar,这意味着将分配一个新的内存块来保存这个 new 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);

这将明确指定如何处理字符串。之后,您的代码应该没问题。

于 2013-07-03T23:23:37.033 回答