Tcl_FSGetNativePath

Difference between version 6 and 7 - Previous - Next
TCL Library command to get a native path.

TCL 8.6.9 man page: [https://www.tcl-lang.org/man/tcl/TclLib/FileSystem.htm]


**Error case**

[HaO]2019-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.

**Windows DLL example**

[HaO]2019-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):

======c
// 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;
}
======

**How to compile**
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



<<categories>> Tcl Library