2011-02-08 4 views
2

사용자 지정 COM 인터페이스에 대한 .net 래퍼를 만들려고합니다.마샬링 Char *. 모든 문자를 얻는 방법

인터페이스는 C++에서 다음과 같이 정의된다 :

DECLARE_INTERFACE_(IDumpAsf, IUnknown) 
{ 
    STDMETHOD(get_UserParams) (THIS_ 
       int *is_auto_start, 
       int *fileSize,   
       int *packetSize, 
       char *baseName, 
       char *filePath 
      ) PURE; 

    STDMETHOD(set_UserParams) (THIS_ 
       int is_auto_start, 
       int fileSize,   
       int packetSize, 
       char *baseName, 
       char *filePath 
      ) PURE; 

    STDMETHOD(enable_Run) (THIS_ 
       bool is_run 
      ) PURE; 
}; 

그리고 C#에서이 같은 인터페이스 선언 :

int is_auto_start; 
int fileSize; 
int packetSize; 
SByte baseName; 
SByte filePath; 

IDumpASF dump = (IDumpASF)asfWriter; 

dump.get_UserParams(out is_auto_start, out fileSize, out packetSize, out baseName, out filePath); 
:

public interface IDumpASF 
{ 

    [PreserveSig] 
    int get_UserParams(
     [Out] out int is_auto_start, 
     [Out] out int fileSize, 
     [Out] out int packetSize, 
     [Out] out System.Sbyte baseName, 
     [Out] out System.SByte filePath 
     ); 

    [PreserveSig] 
    int set_UserParams(
     [In] int is_auto_start, 
     [In] int fileSize, 
     [In] int packetSize, 
     [In] string baseName, 
     [In] string filePath 
     ); 

    [PreserveSig] 
    int enable_Run([In] bool a); 

} 

사용의 exsample에이입니다

나는 영혼을 구축하고 실행할 수는 있지만 모든 캐릭터를 어떻게 얻는 지 알지 못한다. baseName 및 filePath. SByte를 보내면 첫 번째 캐릭터를 되 찾을 수 있지만 나머지는 어떻게 얻습니까? Sbyte [], String, StringBuilder 및 IntPtr과 같은 여러 유형을 시도했습니다. 문자열로 변환하려고 할 때마다 AccessViolationException이 발생합니다.

내가 놓친 바보 같은 것이 있지만 내 환자는 여기에 얇은 것을 입는다.

도움이 많이 필요합니다.

-Svein

답변

2

당신은에서 를 사용하지 않는, 모두 StringBuilder로 인수를 선언해야합니다. 올바르게 전달한 문자열 작성기를 초기화해야하며이 원시 코드가 가비지 수집 힙을 파괴 할 수 없도록 Capacity를 충분히 높게 설정해야합니다. COM 코드를 수정하는 것은 근본적으로 안전하지 않으므로 고려해야 할 사항입니다. BSTR을 사용해야합니다.

+0

안녕 한스. 설명했듯이 StringBuilder를 사용하여이 작업을 수행 할 수 있습니다. 또한 SByte 배열을 사용하여 테스트를 수행했으며, MarshalAs (UnmanagedType.LPArray)를 사용하면 잘 작동합니다. 무엇에 대한 제안? – Svein

+0

@Svein, StringBuilder가 표준 방법입니다. Encoding.Default.GetString()을 사용하여 byte []를 문자열로 다시 변환하지 않아도됩니다. –

+0

Ok. 그럼 StringBuilder에 대해 알아 보겠습니다. 감사. – Svein

0

답장을 보내 주셔서 감사합니다. 몇 번의 시행 착오 끝에 마침내 올바른 설정을 얻었습니다. 당신이 말했듯이, 나는 [Out]없이 StringBuilder를 사용해야합니다. 내 문제는 내가 얻은 가치가별로 의미가 없다는 것이었다. 당신이 말한 것 외에도 MarshalAs 특성을 사용하여 값을 마샬링하는 방법을 지정해야했습니다.

도움을 주셔서 감사합니다.

이 테스트 클래스는 모습입니다 :

System.Text.StringBuilder baseName = new System.Text.StringBuilder(256); 
System.Text.StringBuilder filePath = new System.Text.StringBuilder(256); 

EncirisWrapper.IDumpASF dump = (EncirisWrapper.IDumpASF)asfWriter; 

dump.get_UserParams(out is_auto_start, out fileSize, out packetSize, baseName, filePath); 

그리고이 래퍼는 모습입니다 :

[PreserveSig] 
int get_UserParams(
    [Out] out int is_auto_start, 
    [Out] out int fileSize, 
    [Out] out int packetSize, 
    [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder baseName, 
    [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder filePath  
    ); 

-Svein

관련 문제