开发者

How to create modules in C

I have an interface with which I want to be able to statically link modules. For example, I want to be able to call all functions (albeit in seperate files) called FOO or that match a certain prototype, ultimately make a call into a function in the file without a header in the other files. Dont say that it is impossible since I found a hack that can do it, but I want a non hacked method. (The hack is to use nm to get functions and their prototypes then I can dynamically call the fu开发者_JS百科nction). Also, I know you can do this with dynamic linking, however, I want to statically link the files. Any ideas?


Put a table of all functions into each translation unit:

struct functions MOD1FUNCS[]={
     {"FOO", foo},
     {"BAR", bar},
     {0, 0}
};

Then put a table into the main program listing all these tables:

struct functions* ALLFUNCS[]={
    MOD1FUNCS,
    MOD2FUNCS,
    0
};

Then, at run time, search through the tables, and lookup the corresponding function pointer.


This is somewhat common in writing test code. e.g., you want to call all functions that start with test_. So you have a shell script that grep's through all your .C files and pulls out the function names that match test_.*. Then that script generates a test.c file that contains a function that calls all the test functions.

e.g., generated program would look like:

int main() {
   initTestCode();
   testA();
   testB();
   testC();
}

Another way to do it would be to use some linker tricks. This is what the Linux kernel does for its initialization. Functions that are init code are marked with the qualifier __init. This is defined in linux/init.h as follows:

#define __init          __section(.init.text) __cold notrace

This causes the linker to put that function in the section .init.text. The kernel will reclaim memory from that section after the system boots.

For calling the functions, each module will declare an initcall function with some other macros core_initcall(func), arch_initcall(func), et cetera (also defined in linux/init.h). These macros put a pointer to the function into a linker section called .initcall.

At boot-time, the kernel will "walk" through the .initcall section calling all of the pointers there. The code that walks through looks like this:

extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];

static void __init do_initcalls(void)
{
        initcall_t *fn;

        for (fn = __early_initcall_end; fn < __initcall_end; fn++)
                do_one_initcall(*fn);

        /* Make sure there is no pending stuff from the initcall sequence */
        flush_scheduled_work();
}

The symbols __initcall_start, __initcall_end, etc. get defined in the linker script.

In general, the Linux kernel does some of the cleverest tricks with the GCC pre-processor, compiler and linker that are possible. It's always been a great reference for C tricks.


You really need static linking and, at the same time, to select all matching functions at runtime, right? Because the latter is a typical case for dynamic linking, i'd say.

You obviusly need some mechanism to register the available functions. Dynamic linking would provide just this.


I really don't think you can do it. C isn't exactly capable of late-binding or the sort of introspection you seem to be requiring.

Although I don't really understand your question. Do you want the features of dynamically linked libraries while statically linking? Because that doesn't make sense to me... to static link, you need to already have the binary in hand, which would make dynamic loading of functions a waste of time, even if you could easily do it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜