2013-12-09 4 views
0

저는 C++/CLR 중개자를 통해 기존 C# 코드를 호출 할 Thunderbird 확장 프로그램을 만들고 있습니다. 나는 C++/CLR DLL 또는 스트레이트 C DLL을 사용하여 재생할 수있는 걸림돌을 발견했습니다. 내가 페이지를 반환하는 경우char *가 C DLL에서 js-ctypes로 돌아 오면 사라집니다.

내 기능은 다시 내가 "안녕하세요"를 얻을

__declspec(dllexport)char* strTest2() 
{ 
    char *p = "Hello World"; 
    char buffer[200]; 
    char *q = buffer; 

    strcpy_s(q,200,p); 

    return p; 
} 

입니다. 내가 q를 반환하면 쓰레기 나 행방이 생깁니다. 디버거에서 p와 q를 검사하면 두 데이터 모두 동일한 데이터를 포함하고 있음을 알 수 있습니다.

이 js를 사용하여 함수를 호출하고 있습니다. 모질라 디버거에서

Components.utils.import("resource://gre/modules/ctypes.jsm"); 
var lib = ctypes.open("<path to DLL>"); 

var getStr = lib.declare("strTest2", 
         ctypes.default_abi, 
         ctypes.char.ptr); 

var str = getStr(); 
alert(str.readStringReplaceMalformed()); 

lib.close(); 

는, STR은 형식하려면 CData의 개체로 식별 아래로 충분히 파고 것은 내가 그 캐릭터가 무엇인지 볼 수 없습니다 해요하지만 그것은, 각각의 경우에 문자열을 포함하는 것 보여줍니다.

js-ctype 용 문서는 CData에 의해 직접 참조되는 것이 있으면 계속 유지됩니다. 그러나 이것이 올바르게 일어나지 않는 것처럼 보입니다.

char *r = "\0....\0"; 

가 그 버퍼에 텍스트를 복사하여 연구를 반환하는 strcpy_s를 사용하는 등 내가 큰 '정적'버퍼를 지정하는 경우

다음 문자열을 통해 제공됩니다. 만약 내가 똑바로 C에서 DLL 프로젝트를 사용하고있다. 그러나 C++/CLR DLL 프로젝트를 사용하려고하면 기존의 C# 코드를 가져 와서 하드 코드 된 버퍼에 쓰기를 시도해야한다. 추락하기.

내가 앞으로 나아갈 세 가지 방법이 있습니다.

  • GET 런타임 생성 된 문자열은
  • 는, C++/CLR은 내가 여러 인스턴스에 그 원인이 문제없이 정적 buffer-을 변경할 수 있도록를 얻을 JS-하는 ctypes에 C++/CLR에서 다시 전환에 지속
  • JS가 C++/CLR이 채울 수있는 버퍼를 제공하도록합니다.

누구든지 작동하는 방법을 알고 있습니까?

+2

당신이 첫 번째 유효한 C 코드를 작성했습니다 때까지 C 코드와 상호 운용성하지 마십시오. 지역 변수에 대한 포인터를 반환하는 것은 정의되지 않은 동작입니다. –

답변

3

C의 함수에서 스택 변수에 대한 포인터를 반환 할 수 없습니다. 함수가 반환되면 스택의 해당 부분이 재생되어 포인터가 더 이상 유효하지 않게됩니다.

유효한 대체 방법은 정적 전역 (주의 할 점은 스레드로부터 안전하지 않음)을 사용하거나 함수가 힙에서 새 메모리를 할당하고 포인터를 반환하고 클라이언트가 사용할 수있는 함수를 제공하는 것입니다 그들이 그것으로 끝날 때 기억을 해방하십시오.

+0

Doh. 한번은 C#에 너무 오래 있었음을 알았습니다. :) 감사합니다. 새 메모리를 할당하면 작동합니다. –

3

p를 반환하면 "Hello World"가 반환됩니다. q를 반환하면 쓰레기가 또는 중단됩니다. 디버거에서 p와 q를 검사하면 두 데이터 모두 동일한 데이터 인 이 들어 있음을 알 수 있습니다. DLL이 매핑 /로드로이 주소만큼 유효 -이 동작

이유는 DLL 데이터 세그먼트 내의 고정 된 위치에 저장되는 문자열 상수에 p 점이다./ 재생 런타임에 다시 사용됩니다

그러나 q 포인트가 할당 된 스택 데이터, ...