【发布时间】:2013-07-03 22:48:38
【问题描述】:
我正在尝试使用 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 的代码有一些内部打印,表明该函数的代码确实运行良好。因此,我猜这个问题与函数返回它的值有关。我最好的猜测是,我在调用约定方面遇到了问题。有什么想法吗?
【问题讨论】:
-
当 pinvoke marshaller 试图释放返回的字符串时它会崩溃。您必须将返回类型声明为 IntPtr 并使用 Marshal.PtrToStringAnsi() 自行编组。但是您仍然没有释放字符串的好方法,这将成为内存泄漏,最终将导致您的程序因OOM而崩溃。
-
我能做些什么吗?
-
成功了!谢谢! @HansPassant
-
不,它不起作用。你还在泄漏内存。
-
哦,有什么办法可以解决吗?
标签: c# dll access-violation calling-convention cdecl