2016-09-13 14 views
0

OCX를 C++ 빌더 볼랜드로 만듭니다.C++ 빌더의 com dll에서 BSTR을 혼동했습니다.

  • 로그인
  • 쓰기
  • 읽기
  • DebugOutput
  • GETVAL

내 C# 응용 프로그램이 OCX를 사용하고 있습니다 : 내 OCX 내가 그것을 설명 이러한 기능을 가지고 있습니다. C# 측면에는 단추와 목록 상자가 있습니다. 이 단추는 OCX에서 login 메서드를 호출하고 목록 상자에이 메서드의 출력이 표시됩니다.

OCX 측에서는 login 메서드는 서버 프로그래밍 (소켓 프로그래밍 사용)을 통해 인증을 얻습니다. 그런 다음 Write 함수를 호출하여 소켓에 쓰기 기능을 수행하십시오. 그런 다음 소켓에서 응답을 받고 Read 함수를 호출하여 소켓 응답을 읽습니다.

Read 결과를 읽은 다음 DebugOutput으로 보내 출력 스트림을 디버그하고 GetVal을 호출하여 마지막 주 서버 응답을 찾습니다. 그런 다음 매개 변수를 서로 전달합니다. 모든 C# 측에서 로그인 메소드에 대한 결과 (SUCCESS | FAIL)를 표시합니다.

BSTR을 사용했습니다. (나는 BSTR에 관한 주제를 stackoverflowMSDN에서 읽었다. 그러나 나는 내 솔루션에서 잘 이해하지 못했다고 생각한다.) OCX 측의 코드입니다.

BSTR STDMETHODCALLTYPE TVImpl::Login(BSTR PassWord) 
{ 
    wchar_t wcs1[500]; 
    Var *var=new Var(); 
    //here make the command 
    ................... 
    //get the server response to show to user 
    BSTR read=::SysAllocString(Write(wcs1)); 
    if(read!=NULL) ::SysFreeString(read); 

    return read; 
} 

BSTR STDMETHODCALLTYPE TVImpl::Read() 
{ 
    BSTR str ; 
    try 
    { 
    IdTCPClient1->ReadTimeout=100; 
    str =::SysAllocString(IdTCPClient1->IOHandler->ReadLn().c_str()); 
    } 
    catch(Exception &e) 
    { 
    str= e.Message.c_str(); 
    } 
    str=(DebugOutput(str)); 
    return str; 
} 

BSTR STDMETHODCALLTYPE TVImpl::Write(BSTR str) 
{ 
    IdTCPClient1->IOHandler->WriteLn(str) ; 
    BSTR str2=::SysAllocString(L"TST"); 
    str2=Read(); 
    return str2; 
} 
BSTR STDMETHODCALLTYPE TVImpl::GetVal(BSTR st,BSTR ValTyp) 
{ 
    BSTR res; 
    AnsiString stAnsi; 
    //Do some thing with st and save it to stAnsi 
    ................. 
    res=(BSTR)WideString(stAnsi); 
    return ::SysAllocString(res); 
} 

BSTR STDMETHODCALLTYPE TVImpl::DebugOutput(BSTR st) 
{ 
    Var *val=new Var(); 
    BSTR res; 
    res=GetVal(st,val->CMD_CMD); 
    if(res==val->CMD_AUTHENTICATE) 
     res=GetVal(st,val->XPassword); 
    return res; 
} 

C3 코드에서 매달려있었습니다. 내 문제는 sysAllocString을 사용하는 것입니다. 하지만 나는 각 메소드에서 각각 하나씩 :: sysFreestring을 사용할 때 다시 C# 코드가 걸려있다.

private void button4_Click(object sender, EventArgs e) 
    { 
     VinSockCmplt.Vin vin = new Vin(); 
     listBox1.Items.Add(vin.Login("1234")); 
    } 
+0

같은 코드를 처음 달성하려고했던 것처럼, 그것을 지원 언어 가능 표시하는 데 사용됩니다,하지만 당신은 ... – BugFinder

+0

을 보여 havent 한 무례 할 필요는 없습니다. – BugFinder

+0

실례 합니다만 나쁜 것은 아닙니다. – MHM

답변

5

여러 가지 컴파일러가 다양한 방법으로 컴파일하는 BSTR 또는 모든"복합 "형식을 반환하면 안됩니다 .COM 메서드의 권장 반환 유형은 HRESULT (32 비트 정수)입니다. 방금 할당 된 BSTR을 해제하고 호출자에게 반환하지 않아야합니다

다음

당신이 당신의 방법 레이아웃 수있는 방법입니다. 당신이 .idl 파일에 인터페이스를 정의한다면

HRESULT STDMETHODCALLTYPE TVImpl::Login(BSTR PassWord, /*out*/ BSTR *pRead) 
{ 
    ... 
    *pRead = ::SysAllocString(L"blabla"); // allocate a BSTR 
    ... 
    // don't SysFreeString here, the caller should do it 
    ... 
    return S_OK; 
} 

을, 그것을 다음과 같을 것입니다 :

retval

interface IMyInterface : IUnknown 
{ 
    ... 
    HRESULT Login([in] BSTR PassWord, [out, retval] BSTR *pRead); 
    ... 
} 
는 할당 의미는 그래서 C# 코드는 응답이 var read = obj.Login("mypass")

+0

정말로 도움에 감사드립니다. 나는 이렇게한다 :'* pRead = :: SysAllocString (L "blabla"); // BSTR'을 할당했지만이 오류는''wchar_t * '를'wchar_t * * ''로 변환 할 수 없습니다. 'BSTR'은 * 필요합니까? – MHM

+0

@MHM 해당 오류 메시지는 해당 코드와 일치하지 않습니다. 어쩌면 실수로'BSTR ** pRead'를 매개 변수에 넣었을 것입니다; 또는 당신은'BSTR * pRead =' –

+0

@ M.M이라고 썼습니다. .ridl에 메소드를 만들고 [out, retval]에 param을 넣으면 다음과 같은 에러가 나옵니다 : Out parameters required pointers type. 그런 다음 BSTR을 BSTR *로 변경합니다. 이것은 내 방법입니다 Ans .STDMETHODIMP TVinaImpl :: tst (BSTR * p) {try {p = :: SysAllocString (L "Test bstr232"); } catch (Exception & e) {return Error (e.Message.c_str(), IID_IVina); } 반환 S_OK; }이 오류는 다음을 보여줍니다 : 'wchar_t *'를 'wchar_t *'로 변환 할 수 없습니다. – MHM

5

이 코드에서 실수를 많이하고 있습니다 :

  • if(read!=NULL) ::SysFreeString(read); return read;이 문자열을 해제가 다음 그것을
  • str= e.Message.c_str(); 반환 ... return str;가 포인터를 반환
    이 내 C# 코드입니다 심지어는 BSTR이 아닌 것
  • BSTR str2=::SysAllocString(L"TST"); str2=Read();은 문자열을 할당 한 다음 해당 문자열을 즉시 할당합니다.
  • res=(BSTR)WideString(stAnsi);는 허상 포인터

이 모든이 (누수 제외) 정의되지 않은 동작하며 충돌이 발생할 수 있습니다를 만듭니다.

또한 함수를 반환하는 것이 유효한 지 확실하지 않습니다. BSTR; COM 프로그래밍의 일반적인 규칙은 함수가 HRESULT을 반환하고 모든 "반환 값"이 [out] 매개 변수를 통해 다시 반환된다는 것입니다. 이것은 COM 바인딩이있는 모든 언어와 호환됩니다. 실제로 BSTR을 반환하면 코드 호환성이 제한됩니다. (나는 틀릴 수도있다 - 여기서 교정을 환영 할 것이다). the other question you linked에서 사용 된이 기술을 볼 수 있습니다.


"내 코드가 왜 충돌합니까?", How to AskHow to create a Minimal, Complete, and Verifiable example을 참조하십시오.