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