我正在尝试使用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的代码有一些内部打印,表明该函数的代码确实运行良好。由于这个原因,我想当函数返回它的值时问题是相关的。我最好的猜测是,我遇到了调用约定的问题。有什么想法吗?
答案 0 :(得分:0)
此处的问题很可能与您在Delphi中的PChar
类型有关。在C#中,默认情况下字符串是Unicode,并且在调用func时,实际上会有从PChar
到PWideChar
的转换,这意味着将分配一个新的内存块来保存这个新的{ {1}}。在.NET和Delphi中如何处理字符串之间的这种互操作和差异很可能导致您的PWideChar
。
您可以使用AccessViolationException
属性明确告诉.NET如何处理特定类型:
MarshalAs
将明确指定字符串的处理方式。在那之后,你的代码应该没问题。