TCL Library command to get a native path.
TCL 8.6.9 man page: [L1 ]
HaO2019-05-21: There is no official error case. Nevertheless, Ralf Fassel states on clt 2019-05-21 "Re: Passing file path with ß to C function from DLL":
While the manpage does not document it, looking at the TCL source code there are some code paths that return NULL, so one should check the returned value.
HaO2019-05-21: Adapted from Ralf Fassel on clt 2019-05-21 "Re: Passing file path with ß to C function from DLL", question by Alexandru Dadalau.
A C function should hash a file. The file path is specified from TCL. Platform is Windows. Here is a skeleton (untested, please edit directly):
// the following defines are important and should normally be given in the make file. // To be sure that they are not forgotten, they are given here, accepting an eventual error of redefinition #define USE_TCL_STUBS #define UNICODE #define _UNICODE #define DLL_BUILD #include <Windows.h> #include <tchar.h> #include "tcl.h" int HashCmd(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { wchar_t* fname; FILE * hFile; int hashValue; if (objc <= 1) { Tcl_WrongNumArgs(interp, 1, objv, "path"); return TCL_ERROR; } // Get the native path as a UNICODE value from the function argument. fname = Tcl_FSGetNativePath(objv[1]); // Open the file in binary read mode if ( NULL == fname || NULL == (hFile = _wfopen(fname, L"rb"))) { Tcl_SetStringObj( Tcl_GetObjResult(interp), "Wrong file path",-1); return TCL_ERROR; } // ToDo: // do the hashing here into variable hashValue by reading from file handler hFile // Close the file handler fclose(hFile); // return the resulting hash value Tcl_SetIntObj( Tcl_GetObjResult(interp), hashValue); return TCL_OK; } // DLL entry point, not used here BOOL __declspec(dllexport) WINAPI DllEntryPoint(HINSTANCE hInstance, DWORD seginfo, LPVOID lpCmdLine) { return TRUE; } // TCL setup when the DLL is loaded int __declspec(dllexport) Hash_Init (Tcl_Interp *Interp) { if (Tcl_InitStubs(Interp, "8.1", 0) == NULL) return TCL_ERROR; Tcl_CreateObjCommand(Interp, "hash", HashCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); Tcl_PkgProvide (Interp, "hash", "1.0"); return TCL_OK; } // allow unloading of the DLL int __declspec(dllexport) Hash_Unload (Tcl_Interp *Interp, int flags) { return TCL_OK; }
I compile the checksum.c to a DLL by using msys and MinGW:
Compile in console C:\msys\msys.bat:
cd "C:/mingw-w64/mingw64/bin"
gcc C:/<yourpath>/checksum.c -shared -o C:/Tcl/lib/checksum/checksum.dll -DUSE_TCL_STUBS -IC:/Tcl/include -LC:/Tcl/lib -ltclstub86 -O3 -march=native