Delphi Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
델파이 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
FreePascal/Lazarus
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

델파이 Q&A
Delphi Programming Q&A
[15601] Re:DLL함수호출시 구조체 파라미터에관하여 질문드립니다.
kylix [] 1773 읽음    2015-12-04 17:19
VC++ DLL과 인터페이싱하는데 델파이 고유의 자료형인 동적배열(array of ...)을 사용하니 문제가 생기는 겁니다.

VC코드에 있는것처럼 델파이에서도 정적배열(array[0..최대값] of SmallInt)의 포인터를 사용하세요. VC코드처럼 DLL함수 호출하기 전에 메모리할당하시구요. 다 쓴뒤에도 메모리 해제하시구요.

눈팅이 님이 쓰신 글 :
: 업체에서 dll을받아 VC용샘플을 델파이로 변경하여 진행하고있는데 알 수없는 런타임 에러가 발생하고있어 헤메고있습니다.
: 아무래도 메모리상에서 뭔가 꼬이면서 발생하는것 같은데 해결법을 모르겠습니다.. ㅠㅠ
:
: DioSTT_Edu_ENG_Get_Score 라는 함수를 실행하고나면 문제가 발생하는데.. 요것이 하는일이 RECOGNITION_RESULT_ENG구조체를 레퍼런스 파리미터로받아
: 해당구조체에 값을 채워주는식입니다. 그냥 해당함수만 실행시키고나면 별 문제없는데.. 해당함수실행뒤 채워진값을가지고 뭔가를 하면 그때부터 문제가 생겨버립니다.
: (구조체안에 데이터는 정상적으로 들어와있습니다.)
:
: 짐작되는 부분은 구조체내의 EPD_Buf넘이 smallint형 동적배열인데 요넘에게 Dll함수가 배열원소들을 채워서주게되고나서
: 델파이에서 구조체의 끝점을 찾지못해 발생하는 문제가 아닌가 짐작됩니다...
:
: 아무래도 레코드부분 선언을 제가 잘못한것같은데 뭔지를 모르겠습니다. 업체에도 물어 볼 수도 없는것이.. 업체는 델파이가 뭔지도 모르고 있습니다.ㅡ.ㅡ;;
:
: ※참고로 제가 VC++로 임의Dll을 만들어서 해당 구조체를 가지고 EPD_Buf에 값을 넣어서 리턴 해 보았는데 제가 임의로 만들어서 테스트 해본넘은 문제가 없었습니다..
: 하지만 제 테스트용 과 업체측 제공 dll에서의 EPD_Buf에 데이터를 넣어주는 방식이 틀린지 디버깅걸어보면 업체측Dll에서는 [0]42,[1]35,[2]55.. 이런식인데
: 제 테스트용 dll에서 넣어준 데이터는 실제 디버깅에서는 찾지는못하고 찍어보면 값이 정상적으로 나옵니다.
:
: **** VC 코드
:
: #ifdef WIN32
: #define __decls_dllexport__ __declspec(dllexport)
: #ifdef __cplusplus
: #define DIOSTT_EDU_ENG_API extern "C" __declspec(dllexport)
: #else
: #define DIOSTT_EDU_ENG_API __declspec(dllexport)
: #endif
:
: #define L_ENG_MAX_LIST_CNT            (4096-1) // 최대 리스트 수
: #define L_ENG_MAX_LIST_LEN            128  // 리스트 하나의 최대 길이
: #define L_ENG_MAX_WORD_LEN            32  // 한 단어의 최대 길이
: #define L_ENG_MAX_WORD_CNT            128 // 한 문장내 단어의 최대 수
: #define L_ENG_MAX_RESULT_CNT        10
:
: typedef struct RECOGNITION_RESULT_ENG
: {
:     int nInputLevel;
:     int nInputProfile;
:     int nInputPauseThreshold;
:     int iTextForm;
:     char szInputText[L_ENG_MAX_LIST_CNT*L_ENG_MAX_LIST_LEN];
:     int result_cnt;
:     char result_string[L_ENG_MAX_RESULT_CNT][L_ENG_MAX_LIST_LEN];
:     int result_score[L_ENG_MAX_RESULT_CNT];
:     int total_score;
:     int word_cnt;
:     char word[L_ENG_MAX_WORD_CNT][L_ENG_MAX_WORD_LEN];
:     int word_score[L_ENG_MAX_WORD_CNT];
:     int word_position[L_ENG_MAX_WORD_CNT][2];
:     char phoneme_in_word[L_ENG_MAX_WORD_CNT][L_ENG_MAX_WORD_LEN];
:     char phoneme_cnt_in_word[L_ENG_MAX_WORD_CNT];
:     int phoneme_score_in_word[L_ENG_MAX_WORD_CNT][L_ENG_MAX_WORD_LEN];
:     int phoneme_position_in_word[L_ENG_MAX_WORD_CNT][L_ENG_MAX_WORD_LEN];
:     int word_stress[L_ENG_MAX_WORD_CNT];
:     unsigned char bEPD; // 1: EPD_OK, 0: EPD_FAIL
:     int EPD_position[2];
:     int wpm;
:     char nSNR;
:     int EPD_sample_cnt;
:     short* EPD_Buf;
:
: #ifdef __cplusplus
:     __decls_dllexport__ RECOGNITION_RESULT_ENG();
:     __decls_dllexport__ ~RECOGNITION_RESULT_ENG();
:     __decls_dllexport__ void setEPDBuffer(short *buff, int sampleCount);
:     __decls_dllexport__ void clearEPDBuffer();
: #endif
:
: }Recognition_Result_ENG;
:
: DIOSTT_EDU_ENG_API int DioSTT_Edu_ENG_Get_Score(Recognition_Result_ENG *pScore);
:
:
:
: **** 델파이 2010 코드
: const
:   L_ENG_MAX_LIST_CNT = (4096 - 1);
:   L_ENG_MAX_LIST_LEN = 128;
:   L_ENG_MAX_WORD_LEN = 32;
:   L_ENG_MAX_WORD_CNT = 128;
:   L_ENG_MAX_RESULT_CNT = 10;
:
: type
:   TEpdBuf = array of SmallInt;
:   PEpdBuf = ^TEpdBuf;
:
:   PRecognition_Result_ENG = ^TRecognition_Result_ENG;
:   TRecognition_Result_ENG = record
:     nInputLevel: integer;
:     nInputProfile: integer;
:     nInputPauseThreshold: integer;
:     iTextForm: integer;
:     szInputText: array [0..L_ENG_MAX_LIST_CNT * L_ENG_MAX_LIST_LEN - 1] of ansichar;
:     result_cnt: integer;
:     result_string: array [0..L_ENG_MAX_RESULT_CNT - 1, 0..L_ENG_MAX_LIST_LEN - 1] of ansichar;
:     result_score: array [0..L_ENG_MAX_RESULT_CNT - 1] of integer;
:     total_score: integer;
:     word_cnt: integer;
:     word: array [0..L_ENG_MAX_WORD_CNT - 1, 0..L_ENG_MAX_WORD_LEN - 1] of ansichar;
:     word_score: array [0..L_ENG_MAX_WORD_CNT - 1] of integer;
:     word_position: array [0..L_ENG_MAX_WORD_CNT - 1, 0..1] of integer;
:     phoneme_in_word: array [0..L_ENG_MAX_WORD_CNT - 1, 0..L_ENG_MAX_WORD_LEN - 1] of ansichar;
:     phoneme_cnt_in_word: array [0..L_ENG_MAX_WORD_CNT - 1] of ansichar;
:     phoneme_score_in_word: array [0..L_ENG_MAX_WORD_CNT - 1, 0..L_ENG_MAX_WORD_LEN - 1] of integer;
:     phoneme_position_in_word: array [0..L_ENG_MAX_WORD_CNT - 1, 0..L_ENG_MAX_WORD_LEN - 1] of integer;
:     word_stress: array [0..L_ENG_MAX_WORD_CNT - 1] of integer;
:     bEPD: byte;
:     EPD_position: array [0..1] of integer;
:     wpm: integer;
:     nSNR: ansichar;
:     EPD_sample_cnt: integer;
:     EPD_Buf: TEpdBuf; // <--동적 배열입니다.
:     //EPD_Buf: PEpdBuf;
:     //EPD_Buf: PSmallInt;
:   end;
:
:
:   function DioSTT_Edu_ENG_Get_Score(var UserResult: TRecognition_Result_ENG): integer; stdcall; external 'DioSTT_Edu_ENG.dll';
:   //function DioSTT_Edu_ENG_Get_Score(pUserResult: PRecognition_Result_ENG): integer; stdcall; external 'DioSTT_Edu_ENG.dll';
:
:
: **** 델파이 2010 실행코드
: procedure TFormMain.ENG_GetScore;
: var
:   uRet: TRecognition_Result_ENG;
:   fs: TFileStream;
: begin
:   uRet.EPD_Buf := nil;
:   DioSTT_Edu_ENG_Get_Score(uRet); //요기까지만 실행하면 문제없습니다.
:  
:   //Memo1.Lines.Add('dd'); //<<-- 하다못해 메모에다 아무메세지만찍어도 런타임 에러가 납니다.
:
:   if FileExists(FEPDFile) then
:     fs := TFileStream.Create(FEPDFile, fmOpenReadWrite or fmShareDenyNone)
:   else
:     fs :=TFileStream.Create(FEPDFile, fmCreate);
:
:   try
:     fs.Position := 0;
:     fs.WriteBuffer(uRet.EPD_Buf[0], uRet.EPD_sample_cnt * 2); // <-- EPD_Buf의 값은 정상적으로 들어와서 파일저장까지된 후 런타임 에러가 납니다.
:   finally
:     fs.Free;
:   end;
:
: end;
:
:
: **** 임의 테스트용 Dll코드와 델파이코드
: - dll 코드
: extern "C" __declspec(dllexport)
: int TestApi(Recognition_Result_ENG *pScore) {
:
:     pScore->nInputLevel = 10;
:     pScore->nInputProfile = 15;
:     pScore->nInputPauseThreshold = 25;
:     pScore->iTextForm = 35;
:     strcpy(pScore->szInputText, "babo");
:     pScore->EPD_sample_cnt = 23454;
:
:     pScore->EPD_Buf = (short *)malloc(sizeof(short) * 23454);
:     for (short i = 0; i < pScore->EPD_sample_cnt; i++) {
:         pScore->EPD_Buf[i] = i;
:     }
:
:     return 1;
: }
:
:
: - 델파이코드
: function TestApi(var UserResult: TRecognition_Result_ENG): integer; stdcall; external 'testdll.dll';
: procedure TFormMain.Button1Click(Sender: TObject);
: var
:   i, nResult: integer;
:   uRet: TRecognition_Result_ENG;
: begin
:   uRet.EPD_Buf := nil;
:   nResult := TestApi(uRet);
:
:   Memo1.Lines.Add(IntToStr(nResult));
:   Memo1.Lines.Add(IntToStr(uRet.nInputLevel));
:   Memo1.Lines.Add(IntToStr(uRet.nInputProfile));
:   Memo1.Lines.Add(IntToStr(uRet.nInputPauseThreshold));
:   Memo1.Lines.Add(IntToStr(uRet.iTextForm));
:   Memo1.Lines.Add(uRet.szInputText);
:   Memo1.Lines.Add(IntToStr(uRet.EPD_sample_cnt));
:   for i:=0 to 23453 do begin
:     Memo1.Lines.Add(IntToStr(uRet.EPD_Buf[i]));
:   end;
:
: end;
:

+ -

관련 글 리스트
15600 DLL함수호출시 구조체 파라미터에관하여 질문드립니다. 눈팅이 1721 2015/12/04
15601     Re:DLL함수호출시 구조체 파라미터에관하여 질문드립니다. kylix 1773 2015/12/04
15602         Re:Re:DLL함수호출시 구조체 파라미터에관하여 질문드립니다. 눈팅이 1781 2015/12/04
15603             Re:Re:Re:DLL함수호출시 구조체 파라미터에관하여 질문드립니다. kylix 2346 2015/12/04
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.