从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的代码有一些内部印记,表明该函数的代码确实运行良好。因此,我想当函数返回其值时,问题是相关的。我的最佳猜测是,不知何故,我对电话会议有意见。有什么想法吗?
您的问题很可能与Delphi中的PChar
类型有关。在C#中,字符串默认为Unicode,当调用func时,实际上会有一个从PChar
到PWideChar
的转换,这意味着将分配一个新的内存块来容纳这个新的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);
它将明确指定如何处理字符串。在那之后,您的代码应该是好的。