mirror of https://github.com/svaarala/duktape.git
Sami Vaarala
10 years ago
2 changed files with 133 additions and 10 deletions
@ -0,0 +1,114 @@ |
|||
=========================== |
|||
Duktape C module convention |
|||
=========================== |
|||
|
|||
Overview |
|||
======== |
|||
|
|||
This document provides a recommended convention for writing an init function |
|||
for a C module. The convention allows a module to be initialized manually |
|||
when using static linking, or as part of loading the module from a DLL. |
|||
Modules can be initialized either as part of CommonJS module loading or |
|||
outside of it. |
|||
|
|||
The convention is in no way mandatory and it's perfectly fine to use different |
|||
module loader conventions. However, modules following this convention will be |
|||
easier to share between projects. |
|||
|
|||
Module init function |
|||
==================== |
|||
|
|||
The init function for a module ``my_module`` should contain an initialization |
|||
function of the following form:: |
|||
|
|||
duk_ret_t dukopen_my_module(duk_context *ctx) { |
|||
/* Initialize module in whatever way is most appropriate. |
|||
* Called as a Duktape/C function. |
|||
* |
|||
* Push the module result (e.g. an object with methods) on |
|||
* top of the value stack and return 1 to indicate there's |
|||
* a return value. Temporary values can be left below the |
|||
* return value like in normal Duktape/C functions. |
|||
*/ |
|||
|
|||
duk_push_object(ctx); /* module result */ |
|||
|
|||
duk_put_function_list(ctx, -1, my_module_funcs); |
|||
|
|||
duk_push_int(ctx, 42); |
|||
duk_put_prop_string(ctx, -2, "meaningOfLife"); |
|||
|
|||
return 1; /* return module value */ |
|||
} |
|||
|
|||
The init function is called as a Duktape/C function. When initializing |
|||
the module manually, you should use:: |
|||
|
|||
duk_push_c_function(ctx, dukopen_my_module, 0 /*nargs*/); |
|||
duk_call(ctx, 0); /* or duk_pcall() if you want to catch errors */ |
|||
|
|||
/* Stack top contains module value */ |
|||
|
|||
A DLL loader should use the same convention to call the init function |
|||
after figuring out the init function name and locating it from the DLL |
|||
symbol table. |
|||
|
|||
DLL name |
|||
======== |
|||
|
|||
When a C module is compiled into a DLL, the DLL filename should include |
|||
the module name (``my_module`` in the running example) with any platform |
|||
specific prefix and suffix. For example:: |
|||
|
|||
my_module.so # Linux |
|||
my_module.dll # Windows |
|||
|
|||
A DLL loader should assume that the init function name is ``dukopen_`` |
|||
followed by the module name part extracted from the DLL filename (here, |
|||
``dukopen_my_module()``). |
|||
|
|||
Module name |
|||
=========== |
|||
|
|||
To avoid case conversion and special character issues, module names should |
|||
have the form:: |
|||
|
|||
[a-zA-Z_][0-9a-zA-Z_-]* |
|||
|
|||
This should minimize platform issues. |
|||
|
|||
Mixed Ecmascript / C modules |
|||
============================ |
|||
|
|||
When a module is being initialized by a CommonJS aware module loader, the |
|||
loader should support mixed modules containing both C and Ecmascript code. |
|||
For example:: |
|||
|
|||
my_module.so # C module |
|||
my_module.js # Ecmascript module (CommonJS) |
|||
|
|||
Such a combined module should be loaded as follows: |
|||
|
|||
* First load the C module normally, yielding a return value RET. |
|||
|
|||
* If RET is an object, use it to initialize the CommonJS ``exports`` value |
|||
before loading the Ecmascript module. The Ecmascript module can then |
|||
use whatever symbols the C modules registered, and add further symbols to |
|||
the same exports value. |
|||
|
|||
* If RET is not an object, ignore it and load the Ecmascript module normally. |
|||
|
|||
**FIXME: at the moment the module loader cannot replace the ``exports`` |
|||
value, so it needs copy symbols from RET into ``exports`` one by one.** |
|||
|
|||
Limitations |
|||
=========== |
|||
|
|||
* This convention may not work on all platforms where Duktape itself ports to. |
|||
For instance, a platform might have no DLL support or have filename |
|||
restrictions that don't allow DLLs to be named as specified above. |
|||
|
|||
* The convention is not "CommonJS native": a C module doesn't get an exports |
|||
table and cannot load sub-modules (at least relative to its own CommonJS |
|||
identifier). This is intentional to keep the C module convention as simple |
|||
as possible. |
Loading…
Reference in new issue