2013-07-03 2 views
0

C DLL에서 관리되지 않는 함수를 호출하기 위해 PInvoke를 사용하려고합니다. DLL 소스가 개발자에게 공개 될 수 없기 때문에 그 중 일부는 Delphi에서 다음 선언을 사용하여 함수를 호출했습니다. SAT.dll은 CDECL 호출 규칙과 함께 사용됩니다. 그 구조를 기반 C#에서 DLL에서 C 함수를 호출 할 때 AccessViolationException이 발생했습니다.

function AssociarAssinatura(numeroSessao : Longint; codigoDeAtivacao: PChar; 
       CNPJvalue : PChar; assinaturaCNPJs : PChar) : PChar ; 
       cdecl; External 'SAT.DLL'; 

는 I 동일한 DLL에서 동일한 기능을 테스트하기 위해 C 번호의 다음 콘솔 응용했다. 나는 약간의 연구를했고 델파이의 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

pinvoke marshaller가 반환 된 문자열을 해제하려고하면 충돌이 발생합니다. 반환 형식을 IntPtr로 선언하고 Marshal.PtrToStringAnsi()를 사용하여 반환 형식을 마샬링해야합니다. 하지만 여전히 문자열을 해제 할 수있는 좋은 방법이 없습니다. 그러면 메모리 누수가 발생하여 궁극적으로 OOM으로 프로그램이 중단됩니다. –

+0

내가 할 수있는 일이 있습니까? – Levrak

+0

효과가있었습니다! 감사! @HansPassant – Levrak

답변

0

여기의 문제는 대부분 PChar 유형의 델파이와 관련이 있습니다. C#에서 문자열은 기본적으로 유니 코드이며 func을 호출하면 실제로는 PChar에서 PWideChar으로 변환됩니다. 즉 새로운 메모리 블록이 할당되어이 새로운 PWideChar을 보유하게됩니다. .NET 및 Delphi에서 문자열을 처리하는 방법과이 interop의 차이는 AccessViolationException의 원인 일 가능성이 높습니다.

[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); 

문자열을 명시 적으로 처리하는 방법을 지정합니다

당신은 명시 적으로 어떻게 특정 유형을 처리하는 .NET을 이야기하는 MarshalAs 속성을 사용할 수 있습니다. 그 후, 귀하의 코드가 잘되어야합니다.

+0

슬프게도 여전히 같은 예외가 발생합니다. 문자열에 다른 관리되지 않는 유형을 사용하려고합니까? – Levrak

+0

반환 유형은 어떻게됩니까? 마샬링되어야 하는가? – Levrak

+0

pinvoke 서명에'[return : MarshalAs (UnmanagedType.LPStr)]'을 추가 할 수 있습니다. – aevitas

관련 문제