2010-12-09 2 views
3

저는 C# 응용 프로그램에서 이전 C++ .dll에서 외부 메서드를 호출 할 수없는 이유를 알아 내려고 노력하고 있습니다.C#에서 관리되지 않는 DLL을 호출하는 데 어려움이 있습니다.

int __export FAR PASCAL SimplePGPEncryptFile(
             HWND hWnd1, 
             LPSTR InputFileName, 
             LPSTR OutputFileName, 
             BOOL SignIt, 
             BOOL Wipe, 
             BOOL Armor, 
             BOOL TextMode, 
             BOOL IDEAOnly, 
             BOOL UseUntrustedKeys, 
             LPSTR RecipientList, 
             LPSTR SignerKeyID, 
             int SignerBufferLen, 
             LPSTR SignerPassphrase, 
             int SignerPwdBufferLen, 
             LPSTR IDEAPassphrase, 
             int IDEAPwdBufferLen, 
             LPSTR PublicKeyRingName, 
             LPSTR PrivateKeyRingName); 

여기 내 C# 선언입니다 : 여기

함수 헤더의

 [DllImport("smplpgp_32.dll", CallingConvention = CallingConvention.StdCall)] 
    public static extern int SimplePGPEncryptFile(
     IntPtr hWnd1, 
     [MarshalAs(UnmanagedType.LPStr)] string InputFileName, 
     [MarshalAs(UnmanagedType.LPStr)] string OutputFileName, 
     bool SignIt, 
     bool Wipe, 
     bool Armor, 
     bool TextMode, 
     bool IDEAOnly, 
     bool UseUntrustedKeys, 
     [MarshalAs(UnmanagedType.LPStr)] string RecipientList, 
     [MarshalAs(UnmanagedType.LPStr)] string SignerKeyID, 
     int SignerBufferLen, 
     [MarshalAs(UnmanagedType.LPStr)] string SignerPassphrase, 
     int SignerPwdBufferLen, 
     [MarshalAs(UnmanagedType.LPStr)] string IDEAPassphrase, 
     int IDEAPwdBufferLen, 
     [MarshalAs(UnmanagedType.LPStr)] string PublicKeyRingName, 
     [MarshalAs(UnmanagedType.LPStr)] string PrivateKeyRingName); 

나는 다음 두 가지 오류 중 하나가 (헤더에 선언)을 얻고,이 메소드를 호출 할 때 :

#define SIMPLEPGPENCRYPTFILE_RECIPIENTLISTDOESNOTENDWITHNEWLINE 408 
#define SIMPLEPGPENCRYPTFILE_RECIPIENTLISTDOESNOTSTARTWITHGOODCODECHAR 409 

또한 헤더 상수로 정의된다

#define INCLUDE_ONLYUSERIDS 1 

이이 기능을 호출 작동하는 것으로 알려져 C++ 코드 :

string recipientList = "1CA\n\0"; 

합격 다음 'RecipientList'매개 변수에 대해이 전달

char recipients[512]; 
recipients[0] = INCLUDE_ONLYUSERIDS; 
strcat(strcpy(&recipients[1], rID), "\n"); \\ rID is equal to "CA" 
return 0 == SimplePGPEncryptFile(INI.m_hWnd, 
    (char*)plain, (char*)cipher, 
    0, 
    0, 
    1, 
    0, 
    0, 
    1, // UseUntrustedKeys 
    recipients, 
    0, 0, 
    0, 0, 
    0, 0, 
    PGPKM.pub, 0); //PGPKM.pub is declared earlier 

나에게 '409'오류를 제공을 이 'RecipientList'매개 변수에 대해 '408 '오류가 발생합니다.

char[] recipients = new char[512]; 
recipients[0] = '1'; 
recipients[1] = 'C'; 
recipients[2] = 'A'; 
recipients[3] = '\n'; // also tried '\r', then '\n' 
recipients[4] = Char.MinValue; 
string paramValue = recipients.ToString(); 

누구든지 내 부분에 명백한 감독을 할 수 있습니까? 이 문제를 해결하는 데 필요한 모든 것이있는 것 같지만 예상대로 작동하는 것은 없습니다.

사이드 노트 : 동일한 .dll에서 다른 함수를 성공적으로 호출하고 있습니다. 또한 StringBuilder를 사용하여 RecipientList 매개 변수를 구성하는 방법을 실험했습니다.

의견을 보내 주셔서 감사합니다.

+1

수신자 [0] = INCLUDE_ONLYUSERIDS; - 수신자가 아닙니다. [0] = 1; 받는 사람 [0] = '1'과 다른; - C#은 수신자가됩니다. [0] = (char) 1; – jeffora

+0

받는 사람의 목적은 무엇입니까 [4] = Char.MinValue; –

+0

작동하는 코드에서 strcpy (strcpy (& recipients [1], rID), "\ n") : 결과 문자열은 어떻게 생깁니 까? 512 바이트 후? 또는받는 사람 []이 사용되지 않은 부분을 잘라낼만큼 똑똑합니까? 내 C++ 일 이후로 잠시만 기다려주세요. –

답변

2

TLDR :

string recipientList = (char) 1 + "CA\n\0"; 

어떤 Jeffora의 의견에 따라 파고 것은 ... 그는 아마 맞아, 내 첫 번째 제안은 아마 당신에게 구입하지 않습니다 아무것도 않았다. 나는 몇 가지 테스트 코드를 작성, 여기에 내가 무엇을 발견 :이 코드를 사용하는 경우

는 :

string recipientList = "1CA\n\0"; 

은 당신이 LPSTR로 마샬링 후 함수의 내부에 끝낼 바이트는 다음과 같습니다

49-67-65-10-0 

당신이 원하는 것 같습니다.

이 코드를 사용하는 경우 :

char[] recipients = new char[512]; 
recipients[0] = '1'; 
recipients[1] = 'C'; 
recipients[2] = 'A'; 
recipients[3] = '\n'; // also tried '\r', then '\n' 
recipients[4] = Char.MinValue; 
string paramValue = recipients.ToString(); 

당신이 LPSTR로 마샬링 후 함수의 내부에서 얻을 바이트는 다음과 같습니다

83-121-115-116-101-109-46-67-104-97-114-91-93 

ASCII는 System.Char [ "에 대한 어느 ] ". 따라서 원하는 문자열로 char []을 바꾸려면 엔코더를 사용해야합니다.

첫 번째 문자열이 작동하지 않는 이유는 ... 귀하의 DLL이 실제로 '1'값을 찾고 '1'(49)의 ASCII 문자가 아닌 것 같습니다. 작동 코드에서, 당신은 말 :

recipients[0] = INCLUDE_ONLYUSERIDS; 

곳 INCLUDE_ONLYUSERIDS = 1

이 시도 :

string recipientList = (char) 1 + "CA\n\0"; 


원래 답 : 나는 믿고
가 문제가 있다는 것입니다 Char.ToString()은 char을 유니 코드 문자로 처리하지만 LPWStr가 아닌 LPStr로 정렬합니다. LPStr은 ANSII 문자 열을 찾고 있습니다.

이 문제를 해결하려면 바이트 배열을 사용해보십시오.

byte[] recipients= new byte[512]; 
... 
// Pass this string to SimplePGPEncryptFile 
string recipientsToPass = System.Text.ASCIIEncoding.ASCII.GetString(recipients); 

+0

문자열 형식이 MarshalAs 특성을 통해 ASCII임을 지정 했으므로 Marshaller가 .NET 유니 코드 문자열에서 요청 된 ASCII 문자열로 마샬링을 처리하는지 확실히 확인하십시오. http://msdn.microsoft.com/en-us/library /system.runtime.interopservices.unmanagedtype.aspx – jeffora

+0

흠, 그래, 네 말이 맞아, 아마도 너를 피 묻은 물건으로 사지 않을거야. 나는 자정 이후 질문에 대답하는 것을 멈춰야 만한다. P –

+0

그러나 마샬 러는 문자열 끝에 자동으로 0을 추가하지 않는다? 나는 그것이 그가 수령인들과 뭘하려하는지 생각합니다. [4] = Char.MinValue; –

0

당신은 호출 규칙을 변경하려고 했습니까? C++에서 pascal 호출 규칙으로 함수를 선언하고 C#에서 stdcall로 함수를 선언합니다. 호출 규칙이 일치해야합니다.

관련 문제