Q&A

  • C++과의 데이타 전달의 포인터 문제
델파이 6.0에서 비주얼 c++ 6.0의 dll을 콜하여 원하는 데이타를 리턴받을 려고 합니다.
그런데 좀 이해가 안되는 부분이 있고 에러가 발생하여 문의 드립니다.


디버깅 결과 dll 함수의 //1),//2)번 부분까지는 데이타가 정상입니다. 원하는 데이타가 들어옵니다.

그런데 함수를 빠져 나가면서 //4)번에서 access 에러가 발생합니다. 물론 Rerurn_Getdata도 call by reference를 이용했으나 데이타
를 못받았습니다. Rerurn_Getdata 앞에 var를 붙여도 마찬가지 입니다. 어떤 분은 pchar를 넘길때는 call by reference라고 해도
var를 붙으면 안된다고도 하던데요 암튼 안되었습니다. 선언부에서 pchar대신 pointer를 써도 마찬가지 였구요.

dll부분의 aaa부분의 데이타양이 무지하게 많아서 전체를 call by reference로 하나의 거대한 스트링처럼 통으로 받아서
메모장에 한방에 쫙 뿌릴려고 하는 것이 목적입니다.

dll 함수부분의 ResultData가 포인터값을 전달해서 Rerurn_Getdata포인터값으로 접근할려고 할려고 했는데 아무래도
제가 잘못했기 때문에 문제가 있는게 아닌가 싶습니다.

무슨 방법이 없겠습니까. 좀 자세히 말씀해 주시면(예제까지 조금 해 주시면) 정말 정말 고맙겠습니다.

델파이 부분 변수 선언
PRerurn_Getdata1 pchar;

델파이 선언부
function TTTMsg(arraychar : array of char;datalen : integer ; Rerurn_Getdata : pchar) : integer ; stdcall ; external TTTDLLPOS;


호출하는 부분
procedure TFmRRCCall.Button1Click(Sender: TObject);
var teststr:string;
begin
  if TTTMsg(Inputdata,123 ,) = 1 then
    begin
      teststr:=string(PRerurn_Getdata1);
      DecordingInfo.Lines.Add(teststr);
    end;
end;   //4)



vc++ 부분 dll
구현부
extern "C" int FAR PASCAL EXPORT TTTMsg(unsigned char inputdata[],int LengthData, char *ResultData))
{

char* AAA= BBB;  //1)


ResultData=AAA;  //2)

//memcpy (ResultData, AAA, sizeof(AAA));//3)


return 1;
}
5  COMMENTS
  • Profile
    최용일 2008.04.17 20:56
    양쪽의 Calling Convention은 맞는것 같은데...
    델파이 선언부의 arraychar파라매터는 동적배열로 델파이에만 존재하는 자료형입니다.
    PChar나 포인터, 정적배열로 선언해서 쓰세요...
    메모리도 델파이에서 할당한뒤에 DLL 함수를 호출하세요.

  • Profile
    남가주 2008.04.18 00:31
    그점에 대해서는 DLL 함수를 콜하기 전에 이미 사이즈를 정해서 데이타를 담아 보냅니다.
    즉 const로 선언해서
    const
    Inputdata : array[0..121] of char =
    (
    #$30 , #$EF , #$20 , #$54 , #$16 , #$DC , #$48 , #$A0 , #$08 , #$18
    .........
    .....
    )
    이와같이 미리 정해서 보냅니다.

    그리고 그 데이타를 dll함수에서 이용해서 char *ResultData로 선언된 ResultData요넘을 통해
    포인터로 넘기면 Rerurn_Getdata : pchar로 받아서 데이타를 처리한다는 내용인데 결론적으로
    실제적으로 함수 콜하고 그 결과값을 call by reference로 받는 과정에서  
    즉 if TTTMsg(Inputdata,123 ,PRerurn_Getdata1) = 1
    PRerurn_Getdata1 요넘 변수가 리턴값을 못받는거 같습니다.

    파라메타 전달과정의 데이타 타입의 문제일까요?







  • Profile
    최용일 2008.04.18 02:48
    C는 손논지 좀 오래되서...

    Call By Reference라고 하기에는 좀 무리가 있는듯한데요...
    char *ResultData로 선언하셨으니 DLL내부에서는 2)번처럼 대입하시는것이 아니라 memcpy를 써서 데이터를 옮겨야 할것같구요...
    델파이에서도 arraychar : array of char를 쓰시면 안되고 PChar나 포인터형으로 선언을 하셔야 할것같네요...
    호출할때도 PRerurn_Getdata1를 파라매터로 넣어주시기 전에 리턴받을데이터의 양만큼 메모리를 할당받아야 할것같네요... 보여주신 코드에는 그러한 부분이 없네요...

  • Profile
    남가주 2008.04.18 07:01
    정말 감사합니다.

    님 말씀대로 하니 access error가 발생안하네요. 문제는 말씀대로 arraychar : array of char 요넘 이었습니다.

    그런데 여전히 데이타가 리턴이 안되는 문제는 아직 해결이 안되었습니다.

    님 말씀대로 PRerurn_Getdata1 요넘을 파라메타로 넣어주기 전에 getmem을 써서
    GetMem(PRerurn_Getdata1, 12140);이와같이 메모리를 할당했구요(실제 받는 데이타 보다 더 많이도 잡아 봤습니다. 대략 20000정도요)

    그리고 C++에서도
    ResultData=AAA;  요넘 대신

    memcpy(ResultData,AAA, sizeof(AAA)); 요렇게 하니 copy가 안되더라구요

    그래서 memcpy(&ResultData,&AAA, sizeof(AAA)); 요렇게 하니 ResultData로 copy가 되는 것은 디버깅을 통해 확인했구요. 그런데 정작 델파이에서는 그 값을 못받습니다.
    teststr:=string(PRerurn_Getdata1);로 찍어보면 아무값도 없습니다.

    이 문제만 해결되면 되는데 정말 모르겠습니다.
    부탁좀 드리겠습니다.







  • Profile
    김동원 2008.04.18 18:12
    제 생각에는 DLL Prototype을

    function TTTMsg(arraychar : array of char;datalen : integer ; var Rerurn_Getdata) : integer ; stdcall ; external TTTDLLPOS;

    요렇게 바꾸고...

    call 하는 부분에서

    // 호출하는 부분
    procedure TFmRRCCall.Button1Click(Sender: TObject);
    var teststr:string;
    begin
      SetLength(teststr, 1024); // call back으로 받을 길이가 1024인 경우
      if TTTMsg(Inputdata, 123, teststr[1]) = 1 then
        begin
          DecordingInfo.Lines.Add(teststr);
        end;
    end;

    이렇게 하면 될듯 한데요...
    만약 call back되는 string의 길이가 가변이라면 반환되는 길이를 미리 알수 있는 방법을 DLL에서 제공하거나
    최대길이를 추정하여 SetLength해주고 난 후 실질적은 길이를 반환할 수 있도록 DLL의 함수를 수정해야 할듯 합니다.
    길이를 미리 알 수 있는 방법은 MultiCharToWideChar 함수를 참조하세요..

    도움이