간단한 tcl dll 확장 사례

6884 단어 Tcl/Tk
클립보드에 내용 복사
코드:2008-02-24 09:11/*
* hello.cpp -- A minimal Tcl C extension.
*/
#include
#include <windows.h>

BOOL APIENTRY
DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}

EXTERN_C static int
Hello_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[])
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("Hello, World!", -1));
return TCL_OK;
}

/*
* Hello_Init -- Called when Tcl loads your extension.
*/
EXTERN_C int DLLEXPORT
Hello_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
/* changed this to check for an error - GPS */
if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "hello", Hello_Cmd, NULL, NULL);
return TCL_OK;
}

VC에서 컴파일 프로세스와 Tcl에서 호출 프로세스에 대해 설명합니다.
VC6를 켜면 New->Projects->Win32 Dynamic-Link Library가 완성되면 C++ 소스 파일을 추가합니다.(VC에서는 CPP만 추가할 수 있습니다.) 위의 코드를 그 안에 추가합니다. 그 중의 코드는 원래의 C 코드보다 약간 바뀌었습니다. EXTERN 을 추가했습니다.C 고속 컴파일러. C 입니다.
함수.Project->Settings->C/C++->Preprocessor definitions 가입: USETCL_STUBS, Project->Settings->Link에 tclstub84를 추가합니다.lib, tools->options->directorys->include files->D:/~~DEVP/TCL/TCL8.4.18/GENERIC (내 경로는 이거야. 너의 경로가 다를 수도 있어... 너의 tcl 중의 H를 찾는 거야.
파일), tools->options->directorys->library files ->D:/~DEVP/TCL/TCL8.4.18/WIN/RELEASE (이것은 tcl8.4 lib 파일을 추가한 것입니다. 경로가 다를 수 있습니다. 바로 tcl8.4.lib을 추가한 곳입니다.) 그리고 Hello를 컴파일합니다.
dll.
다음은 tcl에서 확장된 Hello 명령을 어떻게 호출하는지...폴더 만들기, D:/cdcdevp/tcl/tcl8.4.18/library/hello, hello.dll copy 이 폴더에 tclsh.exe중:이 명령으로:pkgmkIndex $path hello.dll path는 hello 폴더의 경로입니다. 경로가 현재 폴더라면:pkgmkIndex ./hello.dll, 명령이 성공하면 pkgIndex가 생성됩니다.tcl 이 파일.tclsh에 package require Hello(Hello 대문자 주의, 현재 package 호출)를 입력하고 Hello 명령을 입력하면 Hello, World!
면 코드는 다음과 같습니다.
http://wiki.tcl.tk/11153, VC에서 win32 dll 프로젝트를 만들 때 파일을 추가할 때 C 원본 파일을 가져올 수 없기 때문에 C++로 만들 수밖에 없습니다. 다행히도 원래 C의
바탕이 아주 작아요~~~
아래 대조원
문서의 원래 내용을 번역하십시오:
이 파일에서 TCL이 DLL에 액세스하는 엔트리 포인트는 Hello 입니다.Init 및 HelloTcl로 확장 담당
해석기의 연결.단계는 다음과 같습니다.
first:Tcl 호출InitStubs(Hello Init? Tcl C API의 다른 부분을 호출할 수 있음)를 만들고 확장된 내용을 만듭니다. (Tcl Create ObjCommand를 사용하여Hello Cmd의 이름을 "hello"로 등록합니다) 그 다음에 Hello package를 제공합니다.
HelloCmd에서 우리는 파라미터를 상관하지 않고 결과를 "Hello, World!"를 포함하는 것으로 설정합니다.의 문자열입니다.매개 변수'-1'은 C의strlen()을 의미한다.양의 수치는 문자열의 길이를 나타낸다.
Hello 정보Cmd, HelloCmd가 호출되었을 때 objv array가 TclObj 구조의 포인터입니다.
클립보드에 내용 복사
코드:At that point you could pass any of those pointers to Tcl_GetString() and get back a pointer to an array of bytes that are a string in Tcl's internal encoding terminated by a NULL byte. If you pass one of those pointers to some other routine, it could happen that the Tcl_Obj might get free'd by that routine. So to prevent that you should Tcl_IncrRefCount(objv) on any argument you need to be sure lives on after being passed to something and balance that with a Tcl_DecrRefCount(objv) when you don't need the insurance any more (Tcl_GetString will not free the Tcl_Obj). Just because the objv isn't freed, you can't conclude that the pointer you get back from Tcl_GetString() might not be freed. Their lifetimes are not the same. So, for any pointer you get back from Tcl_GetString(), you ought to make a copy of that string before you do any thing else, assuming you want to keep it around for a while (see also Tcl_Obj refCount HOWTO).=== . 。
다음은 TclObj, Tcl_Obj는 진정한 OO개념의 Obj가 아니다. 혹은 단지 하나의 용기일 뿐이다. 이 용기는
클립보드에 내용 복사
코드:an integer refCount
representing the number of references to this Tcl_Obj
a char *bytes
being the string representation of the object (under the doctrine `everything's a string'). For a non-empty string, objv->bytes points to Tcl_Alloc()ated memory. For an empty string, objv->bytes points to a static char in the Tcl library that holds a NUL byte.
an integer length
being the length of the string representation
a pointer to a Tcl_ObjType
which contains the type's name, and pointers to functions implementing the four fundamental operations which all Tcl_Obj instances are expected to implement.
a union internalRep
which is used to store up to two pointers of information which is opaque to Tcl.

Stub Libraries 사용
Stub Libraries를 사용하는 이유는 매번 TCL 버전이 발표될 때마다 Tcl CAPI의 변화를 가져올 수 있기 때문입니다. 만약에 만들어진 Tcl 확장 라이브러리에서 이러한 Tcl CAPI를 사용한다면 확장 라이브러리를 다시 컴파일해야 합니다.TCL에서 이 문제를 해결하는 방법: 2개의 라이브러리,main library (tcl84s.lib) 와 stub library (tclstub84.lib) 를 만들었습니다.main library는 모든 코드를 포함하고 stub library는 큰 다이얼 테이블일 뿐이며main library의 각 함수의 주소를 포함합니다.TCL 확장 라이브러리는 점프 테이블을 호출하여 Tcl의 C API를 호출합니다.
만약 tcl 확장 라이브러리에서stubs를 사용하려면 컴파일할 때 설명을 해야 하고 확장된 인트 과정에서 새로운 호출 (Examplea Init) 을 추가해야 합니다. TCLUSE_STUBS compile-time flag(VC에서 Project->Settings->C/C++->Preprocessor definitions 가입: USE TCL STUBS, Project->Settings->Link에 tclstub84.lib을 추가) TclCAPI에 대한 호출을 stub table로 전환합니다.TclinitStubs 호출은 점프 테이블을 초기화할 수 있도록 합니다.
Tcl_CreateObjCommand: 전달된 대응 해석기에 새 명령을 만듭니다. 이 명령에 대응하는 이름은 Hello이고 명령에 대응하는 과정은 HelloCmd, 대응하는 Tcl 명령 Hello가 호출될 때, Tcl 해석기는 대응하는 과정을 호출합니다.Protype: Tcl_CreateObjCommand(interp, cmdName, proc, clientData, delteProc), Tcl_Interp *interp , char *cmdname, Tcl_ObjCmdProc *proc, ClientData clientData(?), Tcl_CmdDeleteProc*deleteProc(cmdName이 해석기에서 삭제되기 전에 호출되는 과정, null이면 명령이 해석기에서 삭제되기 전에 아무것도 할 필요가 없습니다.)
대응 프로세스 HelloCmd의 매개변수 및 결과 비율 및 TclObjCmdProc 유형이 서로 어울리고 TclObjCmdProc의 경우:
클립보드에 내용 복사
코드:typedef int Tcl_ObjCmdProc(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST objv[]);

HelloCmd가 호출되었을 때,clientData와 interp 파라미터는 TclCreateObjCommand의 매개 변수인clientData와interp 매개 변수의 복사본은 전형적으로clientData는 응용과 관련된 데이터 구조를 가리키는데 이 데이터 구조는HelloCmd가 호출되었을 때 어떻게 합니까?Objc와 objv는 Hello에 대한 매개 변수, objc = 매개 변수 대상의 수(명령 이름 포함)를 설명합니다.objv는 매개변수 객체 값입니다(여기서 매개변수 객체는 Tcl Obj).Unlike argv[argv] used in a string-based command procedure, objv[objc] will not contain Null. 여기서 objv에 대한 성명은 CONST로 objv 포인터 그룹의 포인터 요소의 값을 변경할 수 없음을 나타낸다.(do not assign new pointer values to any element of the array). 그러나 개별 매개변수 객체의 내부 대표 값을 변경할 수 있습니다. 예를 들어, Tcl 를 호출할 수 있습니다.GetIntFromObject on objv[2]에서 이 대상의 인덱스 리프레젠테이션을 얻을 수 있습니다. 이 호출은 objv[2]가 가리키는 대상의 유형을 바꿀 수 있지만 objv[2]의 지향은 바뀌지 않습니다.
확장 명령 프로세스, 이 예에서는 HelloCmd에서 인덱스 코드: TCL 을 반환해야 합니다.OK, TCL_ERROR, TCL_RETURN, TCL_BREAK, or TCL_CONTINUE.프로세스가 비어 있지 않은 결과를 되돌리려면 TclSetobjResult를 사용하여 해석기의 결과를 설정합니다.

좋은 웹페이지 즐겨찾기