2017-10-27 8 views
-1
내가 델파이 2007 년에 수입 된 기능을 실행하려고

:델파이 2007 EXE 및 C++ DLL : 디버그 출력 : 027D5009 과거를 수정 027D4FF8에서 힙 블록이 9 개 프로세스의 크기를 요청

function getOfficialCardNumber(): WideString ; cdecl; external 'idcapp.dll'; 

을하지만, 몇 초 후 (에

77BD37D6 C6055562C17700 mov byte ptr [$77c16255],$00 

을이 말한다 : 디버그 구성은)는 여기 중지

Debug Output: Heap block at 027D4FF8 modified at 027D5009 past requested size of 9 Process PreglediZaDom.exe (23672) 

언급 기능 WA를 C++로 작성된 (Visual Studio)

WideString을 PWideString 및 다른 것으로 변경하려고 시도했지만 성공하지 못했습니다. 누구든지 문제가 될 수있는 것을 알고 있습니까?

Public Function pisBstrToString(bstr) As String 

    Dim bArray() As Integer 

    Dim longArray() As Long 

    Dim str   As String 

    Dim i   As Integer 

    bArray = pisStringToBArray(bstr) 
    longArray = pisBArrayToLongArray(bArray) 

    str = "" 

    For i = 1 To UBound(longArray) 

     If longArray(i) > 0 And longArray(i) < 256 Then 
      str = str & Chr(longArray(i)) 
     Else 
      str = str & pisLongToUnichar(longArray(i)) 
     End If 

    Next i 

    pisBstrToString = str 

End Function 

내가 지금 C++에서 기록 된 기능은 다음과 같이 내 보낸 알고 :

BSTR _stdcall getOfficialCardNumber() 
+0

아마도 번역이 잘못 되었습니까? 함수는 C 또는 C++ 헤더에서 어떻게 선언됩니까? 또는 VB6에서 함수가 어떻게 선언됩니까? –

+0

C++ 헤더가 없습니다 (dll은 다른 사람이 작성한 것입니다). 공용 선언 함수 getOfficialCardNumber Lib "C : \ WINDOWS \ system32 \ idcapp.dll"() VB6에서 문자열이 선언되어 있으므로 –

+0

VB6에서'cdecl'을 처리 할 수 ​​없으므로'stdcall'이어야합니다. 결과는 실제로 'WideString'입니다. –

답변

1

VB6가하는 유사한 응용 프로그램에서

하지만, VB6로 작성 그들은 나에게 문자열을 변환하는이 기능을 준 cdecl을 지원하지 않으며 stdcall 만 지원합니다. 바로 거기에서 델파이 코드에서 잘못된 호출 규칙을 사용하고 있습니다. 호출 스택이 잘못 관리됩니다. 아니지만 외부 DLL 함수의 String 반환 값 -

델파이의 WideString 유형은 VB6가 자신의 문자열을 사용 않는 COM BSTR 문자열에 대한 래퍼입니다! VB6에서 출력으로 BSTR을 예상하거나 수락했다고해도 DLL 함수는 다른 반환 형식과 마찬가지로 EAXcpu 레지스터에 BSTR 포인터를 반환합니다. 그러나 반환 유형으로 WideString을 처리 할 때 델파이는 EAX을 사용하지 않습니다. 대신 숨겨진 var 매개 변수로 전달됩니다. 자세한 내용은 Why can a WideString not be used as a function return value for interop?을 참조하십시오. DLL 함수가 char* 포인터를 반환하는 경우

, 당신은 PAnsiChar로 함수 반환 값을 선언해야합니다 :

function getOfficialCardNumber(): PAnsiChar; stdcall; external 'idcapp.dll'; 

을 그렇지 않으면, 그것은 wchar_t* 포인터 1을 반환하는 경우, 당신은을 선언해야합니다 함수의 반환 값 대신 PWideChar 등 :

function getOfficialCardNumber(): PWideChar; stdcall; external 'idcapp.dll'; 

어느 쪽이든, 당신이 다루는 또 다른 문제가 - 사람 이 메모리를 소유하고 있으며 어떻게 해제해야합니까? 델파이는 을 직접적으로로 반환 할 수 없으므로 DLL에 의해 메모리가 반환되므로 메모리가 어떻게 할당됩니까?

  • DLL 내에서 정적으로 정적 인 경우 전혀 해제 할 필요가 없습니다.

  • 동적으로 메모리 관리자가 할당 한 경우?

    • 는 DLL 내부에 메모리 관리자 인 경우에는 당신이 그래서 같은 메모리 관리자를 사용하여 해제 할 수 있습니다 사용하여 수행하는 경우, 다음 DLL이 포인터를 받기 위해 별도의 기능을 보내야합니다.

    • 그것이 OS가 제공하는 메모리 API (LocalAlloc()/GlobalAlloc(), IMalloc.Alloc()imalloc/CoTaskMemAlloc() 등) 다음 델파이 코드를 직접 (등 IMalloc.Free()/CoTaskMemFree()LocalFree()/GlobalFree()) 해당 메모리 해제 함수를 호출이면 .


      1

: 그것은 실제로 BSTR 포인터로를 발생하는 경우, 당신은 당신이 그것을 사용하여 수행하는 경우 SysFreeString()에 반환 된 포인터를 전달해야합니다.

+0

이 dll에는 login이라는 프로 시저가 있습니다. procedure login (uName, pwd : WideString); cdecl; 외부 'idcapp.dll'; 만약 내가 이렇게 선언하면 : procedure login (uName, pwd : String); cdecl; 외부 'idcapp.dll'; 그것은 작동하지 않으므로 매개 변수가 WideString 형식이어야하므로 리턴 매개 변수도 WideString이어야한다고 생각합니다. –

+0

네, 델파이의 경우 –

+0

문자열 'String' <>'WideString'을 EAX 레지스터에서 중지합니다. interop이 관련되어 있으면 스위치를 전환 할 수 없습니다. DLL 함수가'WideString'을 필요로한다면'WideString'을 전달하십시오. 하지만 실제로'PWideChar'를 기대하지 않는 것이 확실합니까? DLL이 Delphi로 작성 되었습니까? 아니면 다른 것입니까? –