Tcl pathInFilesystemProc 获取当前文件系统
Tcl pathInFilesystemProc get current filesystem
使用 tcl 创建 vfs 时 api 如何在 Tcl_Filesystem.pathInFilesystemProc
中获取当前文件系统
我的代码看起来像这样:
typedef struct {
FILE* dbFile;
/*...*/
} FSBackend;
void createFS(const char* dbFile)
{
FSBackend* fsback = (FSBackend*)malloc(sizeof(FSBackend));
initDb(fsback,dbFile);
Tcl_Filesystem tfs;
tfs.typeName="Db Fs";
tfs.structureLength = sizeof(Tcl_Filesystem);
tfs.version = TCL_FILESYSTEM_VERSION_1;
tfs.pathInFilesystemProc = inFsProc;
/*...*/
Tcl_FSRegister((void*),tfs);
}
int inFsProc(Tcl_Obj* pathPtr,ClientData* cd)
{
/* How do I get my FSBackend struct here */
FSBackend* bk = /* ? */
int len;
const char* searchPath = Tcl_GetStringFromObj(pathPtr,&len);
char* foundPath = findFileInDb(searchPath,bk);
if (foundPath == 0) {
return -1;
}
cd = buildInternalRep(foundPath,bk);
return TCL_OK;
}
/**
...
*/
int main()
{
createFS("db1.db");
createFS("db2.db");
}
如何在 inFsProc
中取回传递给 Tcl_FSRegister
的结构?
Tcl_FSData
函数说它可以得到它,但我需要得到一个 Tcl_Filesystem 指针
这很奇怪。 clientData
句柄 不是 用于指定挂载点,而是文件系统 type 的单独功能。 Tcl 内部使用 Tcl_FSRegister
根本不使用它。最接近规范使用的代码是 tclvfs 包。
https://github.com/tcl-mirror/tclvfs/blob/master/generic/vfs.c#L385 向我们展示了用法:
static void
Vfs_RegisterWithInterp(interp)
Tcl_Interp *interp;
{
ClientData vfsAlreadyRegistered;
/*
* We need to know if the interpreter is deleted, so we can
* remove all interp-specific mounts.
*/
Tcl_SetAssocData(interp, "vfs::inUse", (Tcl_InterpDeleteProc*)
Vfs_UnregisterWithInterp, (ClientData) 1);
/*
* Perform one-off registering of our filesystem if that
* has not happened before.
*/
vfsAlreadyRegistered = Tcl_FSData(&vfsFilesystem);
if (vfsAlreadyRegistered == NULL) {
Tcl_FSRegister((ClientData)1, &vfsFilesystem);
Tcl_CreateExitHandler(VfsExitProc, (ClientData)NULL);
Tcl_CreateThreadExitHandler(VfsThreadExitProc, NULL);
}
}
如您所见,clientData
实际上只是用作标记,因此代码知道是否进行一次性初始化。
要发现装载映射是什么,您需要保留内部结构。强烈建议您在代码中使 Tcl_Filesystem
结构实例本身成为全局的(或者更确切地说 static
在文件范围内)。
使用 tcl 创建 vfs 时 api 如何在 Tcl_Filesystem.pathInFilesystemProc
我的代码看起来像这样:
typedef struct {
FILE* dbFile;
/*...*/
} FSBackend;
void createFS(const char* dbFile)
{
FSBackend* fsback = (FSBackend*)malloc(sizeof(FSBackend));
initDb(fsback,dbFile);
Tcl_Filesystem tfs;
tfs.typeName="Db Fs";
tfs.structureLength = sizeof(Tcl_Filesystem);
tfs.version = TCL_FILESYSTEM_VERSION_1;
tfs.pathInFilesystemProc = inFsProc;
/*...*/
Tcl_FSRegister((void*),tfs);
}
int inFsProc(Tcl_Obj* pathPtr,ClientData* cd)
{
/* How do I get my FSBackend struct here */
FSBackend* bk = /* ? */
int len;
const char* searchPath = Tcl_GetStringFromObj(pathPtr,&len);
char* foundPath = findFileInDb(searchPath,bk);
if (foundPath == 0) {
return -1;
}
cd = buildInternalRep(foundPath,bk);
return TCL_OK;
}
/**
...
*/
int main()
{
createFS("db1.db");
createFS("db2.db");
}
如何在 inFsProc
中取回传递给 Tcl_FSRegister
的结构?
Tcl_FSData
函数说它可以得到它,但我需要得到一个 Tcl_Filesystem 指针
这很奇怪。 clientData
句柄 不是 用于指定挂载点,而是文件系统 type 的单独功能。 Tcl 内部使用 Tcl_FSRegister
根本不使用它。最接近规范使用的代码是 tclvfs 包。
https://github.com/tcl-mirror/tclvfs/blob/master/generic/vfs.c#L385 向我们展示了用法:
static void
Vfs_RegisterWithInterp(interp)
Tcl_Interp *interp;
{
ClientData vfsAlreadyRegistered;
/*
* We need to know if the interpreter is deleted, so we can
* remove all interp-specific mounts.
*/
Tcl_SetAssocData(interp, "vfs::inUse", (Tcl_InterpDeleteProc*)
Vfs_UnregisterWithInterp, (ClientData) 1);
/*
* Perform one-off registering of our filesystem if that
* has not happened before.
*/
vfsAlreadyRegistered = Tcl_FSData(&vfsFilesystem);
if (vfsAlreadyRegistered == NULL) {
Tcl_FSRegister((ClientData)1, &vfsFilesystem);
Tcl_CreateExitHandler(VfsExitProc, (ClientData)NULL);
Tcl_CreateThreadExitHandler(VfsThreadExitProc, NULL);
}
}
如您所见,clientData
实际上只是用作标记,因此代码知道是否进行一次性初始化。
要发现装载映射是什么,您需要保留内部结构。强烈建议您在代码中使 Tcl_Filesystem
结构实例本身成为全局的(或者更确切地说 static
在文件范围内)。