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
[15600] DLL함수호출시 구조체 파라미터에관하여 질문드립니다.
눈팅이 [songy1] 1714 읽음    2015-12-04 17:06
업체에서 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함수호출시 구조체 파라미터에관하여 질문드립니다. 눈팅이 1714 2015/12/04
15601     Re:DLL함수호출시 구조체 파라미터에관하여 질문드립니다. kylix 1769 2015/12/04
15602         Re:Re:DLL함수호출시 구조체 파라미터에관하여 질문드립니다. 눈팅이 1771 2015/12/04
15603             Re:Re:Re:DLL함수호출시 구조체 파라미터에관하여 질문드립니다. kylix 2341 2015/12/04
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.