Tcl pathInFilesystemProc get current filesystem - c

When creating a vfs using the tcl api how do you get the current filesystem in Tcl_Filesystem.pathInFilesystemProc
My code looks something like this:
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");
}
How do I, in inFsProc get back the struct I passed into Tcl_FSRegister?
The Tcl_FSData function says it can get it but I would then need to get a Tcl_Filesystem pointer

That's a weird one. The clientData handle there is not used to specify a mount point, but rather a separate capability of the filesystem type. Tcl's internal use of Tcl_FSRegister doesn't use it at all. The code which is as close as anything to a canonical use of it is the tclvfs package.
https://github.com/tcl-mirror/tclvfs/blob/master/generic/vfs.c#L385 shows us the use:
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);
}
}
As you can see, the clientData there is really just being used as a marker so the code knows whether to do one-time initialisation.
To discover what the mount mapping is, you'll need to keep internal structures. You're strongly recommended to make the Tcl_Filesystem structure instance itself be global (or rather static at file scope) in your code.

Related

How do I avoid circular dependancy coding UNDO/REDO in C?

//I'm moving this note to the top: I'm recreating OOP with structs and associated methods like int MyClass_getInt(MyClass* this)
I'm coding a small DAW in C. I have my Timeline and Region classes in Timeline.h. I would like my UndoRedoStack class to be able to work with multiple Timeline instances so I'd like the UndoRedoStack to be in a separate .c/.h file.
This line of thinking seems to require the TimelineUndoRedoCommand class to know about Timelines and Regions because it needs to backup pre-existing states.
It also requires Timelines to know about TimelineUndoRedoCommands so that it can fire them into the UndoRedoStack.
This seems to be a circular dependency. How should I structure this so that I can avoid circular dependencies?
//
I ended up asking Timeline.h to write all the code that needs it but house the UndoRedo separately like so:
/*
UndoRedoCmd
*/
typedef struct _UndoRedoCmd{
void* content;
char* name;
}UndoRedoCmd;
/*
UndoRedoStack
*/
typedef struct _UndoRedoStack{
t_LinkList* undoStack;
t_LinkList* redoStack;
bool redoingNow;
void (*redoFunc)(UndoRedoCmd* redoThis);
void (*undoFunc)(UndoRedoCmd* undoThis);
}UndoRedoStack;
/*
UndoRedoCmd
*/
UndoRedoCmd* UndoRedoCmd_New(char* name, void* content){
UndoRedoCmd* this = malloc(sizeof(UndoRedoCmd));
this->name=name;
this->content=content;
return this;
}
void UndoRedoCmd_Kill(UndoRedoCmd* this){
/*this should never be used. instead the
user of UndoRedoStack should provide
a custom killer which simply calls
free after freeing the contents
*/
}
/*
UndoRedoStack
*/
UndoRedoStack* UndoRedoStack_New(
void (*redoFunc)(UndoRedoCmd*),
void (*undoFunc)(UndoRedoCmd*),
void (*freeLinkFunction)(void*)
){
/*
redoFunc is meant to take the content of the command and redo some action with it.
undoFunc is the opposite
freeLinkFunction is meant should free a LinkList_Link with the custom UndoRedo content inside of it.
*/
UndoRedoStack* this = malloc(sizeof(UndoRedoStack));
this->undoFunc=undoFunc;
this->redoFunc=redoFunc;
this->redoStack = LinkList_New();
this->redoStack->autoFree=2;
this->redoStack->customFree=freeLinkFunction;
this->undoStack = LinkList_New();
this->undoStack->autoFree=2;
this->undoStack->customFree=freeLinkFunction;
return this;
}
void UndoRedoStack_Kill(UndoRedoStack* this){
LinkList_Free(this->undoStack);
LinkList_Free(this->redoStack);
free(this);
}
void UndoRedoStack_do(UndoRedoStack* this,char* name,void* undoredoinfo){
UndoRedoCmd* mycmd = UndoRedoCmd_New(name, undoredoinfo);
LinkList_push(this->undoStack, mycmd);
}
void UndoRedoStack_undo(UndoRedoStack* this){
if(this->undoStack->length==0){
return;
}
UndoRedoCmd* undoMe = (UndoRedoCmd*)LinkList_pop(this->undoStack);
this->undoFunc(undoMe);
LinkList_push(this->redoStack, undoMe);
}
void UndoRedoStack_redo(UndoRedoStack* this){
if(this->redoStack->length==0){
return;
}
UndoRedoCmd* redoMe = (UndoRedoCmd*)LinkList_pop(this->redoStack);
this->redoFunc(redoMe);
LinkList_push(this->undoStack, redoMe);
}

object oriented approach in c program

I don't have much experience in Object oriented programming.I am trying to create an object in c which will have its own methods.
I have declared structure which have pointers to function. All instance of this variable are going to point same function. But currently I need to initialize every instance of variable as in main (Line 1 and Line 2). So is there any method that will initialize its default value when I declare it?
#include <stdio.h>
#include <stdlib.h>
typedef struct serialStr Serial;
struct serialStr
{
void(*init)(Serial*);
void(*open)();
void(*close)();
};
void open()
{
printf("Open Port Success\n");
return;
}
void close()
{
printf("Close port Success\n");
return;
}
void init(Serial* ptr)
{
ptr->open = open;
ptr->close = close;
}
int main()
{
Serial serial,serial_2;
serial.init = init;
serial.init(&serial); // Line1
serial_2.init = init;
serial_2.init(&serial_2); // Line2
serial.open();
//rest of code
serial.close();
serial_2.open();
serial_2.close();
return 0;
}
In C, the standard way would be to declare an initializer macro:
#define SERIAL_INITIALIZER { .init = init, .open = open, /* and others */ }
Serial serial = SERIAL_INITIALIZER;
In most cases in C there is simply no need for dynamic intialization of variables. You only need it for malloced objects.
C++ add some automatization by calling constructor/destructor. In pure C is no way to do so. You should do all steps manually: create and initialize object (call constructor-like function for structure), call functions by pointers from the structure instance, call destructor (it should destroy the instance and free related resources).
If is no polymorphism in your task then use simple way - without pointers to functions, but each function (method) should take pointer to the object.
Common case example:
struct MyStruct
{
// data
};
struct MyStruct* createMyStruct(/* maybe some input */)
{
// create, init and return the structure instance
}
void destoyMyStruct(struct MyStruct* obj)
{
// free resources and delete the instance
}
void doSomeAction(struct MyStruct* obj /* , some other data */)
{
// ...
}
int main()
{
struct MyStruct* object = createMyStruct();
doSomeAction(object);
destoyMyStruct(object);
return 0;
}
Edit 1: macro is only for very simple cases and error-prone way.
Typically, you would do this through "opaque type". Meaning that you declare an object of incomplete type in your header:
typedef struct Serial Serial;
And then in the C file, you place the actual struct definition. This will hide the contents of the struct to the caller (private encapsulation). From your constructor, you could then set up private member functions:
struct Serial
{
void(*init)(void);
void(*open)(void);
void(*close)(void);
};
// private member functions:
static void open (void);
...
// constructor:
Serial* SerialCreate (void)
{
Serial* s = malloc(sizeof (*s));
...
s->open = open;
return s;
}
This means that if you wish to inherit the class, you will only need to change the constructor.
Though of course, if you wish to implement true polymorphism, you don't want to change any code. You could solve this by passing the init function as parameter to the constructor.
header file:
typedef void init_func_t (void);
c file:
// constructor:
Serial* SerialCreate (init_func_t* init)
{
Serial* s = malloc(sizeof (*s));
...
init();
return s;
}
And then from the init function in the inherited class, set all private member functions.

Share variables internally across functions

Suppose I have a function like this:
static int init_processing(char *buf, FILE *stream, enum operationMode mode) {
/* save index of `stream' in current operations */
/* start processing */
/* save some important variables for continue_processing */
off_t position;
enum operationMode _mode;
return num_processing_operations_left;
}
.. that I would be calling occasionally. And I have another function that does the actual processing I want:
static int continue_processing(FILE *stream) {
/* lookup the index of `stream' in current operations */
/* do some stuff */
/* save some static variables */
static off_t left = position;
static void *some_ptr;
return --num_processing_operations_left;
}
I also have a cleaning function to invoke when finishing up a certain operation:
static int end_processing(FILE *stream) {
/* check */
if (num_processing_operations_left)
return 1;
/* clean everything */
return 0;
}
As you can see, this related functions technique is very familiar that it is used by the standard library itself (e.g [malloc, free, realloc], [fdopen, fopen, fclose]).
What I want to achieve here, is how to share some variables across a bunch of functions ?
I thought of two solutions:
Put each set of functions in a file of their own, providing static variables valid only for the file itself.
Use only one function that takes an extra enum parameter as a mode and structure the function accordingly.
But these solutions aren't actually solutions, they're just workarounds to cope with the problem. So, is there any standard technique to share variables among functions ?
Create a context structure keeping all you need:
struct Context
{
FILE * stream;
off_t position;
unsigned num_processing_operations_left;
/* define some more important variables */
}
and pass it to all functions in question:
static int init_processing(struct Context * pctx, char *buf, enum operationMode mode);
static int continue_processing(struct Context * pctx);
static int end_processing(struct Context * pctx);
int main(void)
{
struct Context ctx = {0};
/* init ctx here */
int result = init_processing(&ctx, ...);
...
result = continue_processing(&ctx);
...
result = end_processing(&ctx);
...
}

creating C threads from text file

Let's say I have a text file composed like this
#####
typeofthread1
#####
typeofthread2
etc...
in my main I want to read that file, get the strings typeofthread1, typeofthread2 and create different threads using
pthread_t threads[NUM_THREADS];
for (i=0;i<NUM_THREADS;i++)
pthread_create(&threads[i], NULL, -> HERE <- , void * arg);
how can I put the just read typeofthread1, typeofthread2 strings into -> HERE <- making the main create two threads that point to two different thread prototype?
I want to do this because I want to create a program that creates different types of threads, depending on what I want to do, and choosing that from text file (sort of a configuration file)
any suggestion?
Map the string names to function pointers.
void * thread_type_1 ( void * );
void * thread_type_2 ( void * );
typedef void * (*start_routine_t)(void *);
typedef struct mapping_t {
const char * name;
start_routine_t function;
} mapping_t;
const mapping_t mappings[] = {
{"thread-type-1", &thread_type_1},
{"thread-type-2", &thread_type_2},
};
const size_t mapping_count =
sizeof(mappings)/sizeof(mappings[0]);
To select the proper thread function, loop over items in mappings and grab the function when the name matches.
start_routine_t get_start_routine ( const char * name )
{
size_t i;
for ( i=0; i < mapping_count; ++i )
{
if (strcmp(name,mappings[i].name) == 0) {
return mappings[i].function;
}
}
return NULL;
}
In wherever you launch the thread, you can use this as:
start_routine_t start_routine;
/* find start routine matching token from file. */
start_routine = get_start_routine(name);
if (start_routine == NULL) {
/* invalid type name, handle error. */
}
/* launch thread of the appropriate type. */
pthread_create(&threads[i], NULL, start_routine, (void*)arg);
A better approach would be to create a default thread_dispatch function that you launch all your pthreads with. This dispatch function would take a structure that contained a void* to a structure that contained the thread-specific data, and a string that specified the type of the thread-function you wanted to run. You could then, using a look-up table mapping the string to the function-pointer type created in a code-module, find the appropriate function pointer, and pass the thread-specific data to that function. So this would look something like the following:
typedef struct dispatch_data
{
char function_type[MAX_FUNCTION_LENGTH];
void* thread_specific_data;
} dispatch_data;
void* thread_dispatch(void* arg)
{
dispatch_data* data = (dispatch_data*)arg;
//... do look-up of function_pointer based on data->function_type string
return function_pointer(data->thread_specific_data);
}

using malloc for the life of the program

gcc 4.4.4 c89
I have always thought of using malloc for the life of the project for being the scope.
But I am just wondering if my idea is the best practice. For example, I initalize an instance of the struct in main. And create 2 functions for creating and destroying. I am just wondering if this is the right thing to do.
I have some skeleton code below.
Many thanks for any advice,
typedef struct Network_dev_t {
size_t id;
char *name;
} Network_dev;
Network_dev* create_network_device(Network_dev *network)
{
network = malloc(sizeof *network);
if(network == NULL) {
return NULL;
}
return network;
}
void do_something(Network_dev *network)
{
/* Do something with the network device */
}
void destroy_network_device(Network_dev *network)
{
free(network);
}
int main(void)
{
Network_dev *network = NULL;
network = create_network_device(network);
/* Do something with the network device */
do_something(network);
destroy_network_device(network);
return 0;
}
Looks good.
I have a point or 2 about create_network_device
Network_dev* create_network_device(Network_dev *network)
no need to pass in a pointer; I'd rather have Network_dev* create_network_device(void)
{
network = malloc(sizeof *network);
the if is not really necessary; if malloc failed the return network at the end of the function is the same as return NULL.
if(network == NULL) {
return NULL;
}
If the allocation succeeded you might want to insure the struct members are in a know state here
/* if (network) { */
/* id = 0; */
/* name = NULL; */
/* } */
return network;
}
This code looks fine to me. I agree with pmg that your create_network_device could use a little work. Just to pull together what he said and make things clearer, here is exactly how I would write the function:
Network_dev *create_network_device()
{
Network_dev *network = malloc(sizeof(*network));
if (network) {
network->id = 0;
network->name = NULL;
}
return network;
}
It is best to allocate memory and free memory in the same function. Just like you open and close files in the same function. You did this by creating and destroying a Network_dev in the main() function, which is good. This makes it easy to confirm that all malloced locations are also freed.
It is best to malloc() something as late as possible and free() it as soon as possible. That is, hold the memory for as short as possible. If your program's job is to do something with Network_dev, you did all right. If your program does a lot of other things, you should do them before malloc() or after free().

Resources