업체에서 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;
|