7,801
edits
Line 17: | Line 17: | ||
# Write a JS module interfacing with js-ctypes and the C wrapper. | # Write a JS module interfacing with js-ctypes and the C wrapper. | ||
# Fix existing JS code (gui.js, etc) to use the JS module. | # Fix existing JS code (gui.js, etc) to use the JS module. | ||
'''Note''': Because of the number of layers, it is important to respect the convention on naming which differs from layer to layer. | |||
Examples: | |||
* '''component''': zimAccessor | |||
* '''component path''': src/components/zimAccessor | |||
* '''library name''': zimAccessor | |||
* '''library path''': src/zimAccessor | |||
* '''C++ library files''': zimAccessor.cpp zimAccessor.h | |||
* '''C Wrapper files''': ZimAccessorWrapper.cpp ZimAccessorWrapper.h | |||
* '''Tester path''': src/zimTester/ | |||
* '''C++ tester file''': zimTester.cpp | |||
* '''C Wrapper tester file''': zimCTester.c | |||
=== Rewrite the C++ component into a C++ library === | === Rewrite the C++ component into a C++ library === | ||
Line 37: | Line 50: | ||
* C++ Component code [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/components/zimAccessor/zimAccessor.cpp?revision=2920&view=markup example] | * C++ Component code [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/components/zimAccessor/zimAccessor.cpp?revision=2920&view=markup example] | ||
* C++ library [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/zimAccessor/zimAccessor.cpp?revision=2920&view=markup example] | * C++ library [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/zimAccessor/zimAccessor.cpp?revision=2920&view=markup example] | ||
* C++ library header [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/zimAccessor/zimAccessor.h?revision=2811&view=markup example] | |||
Rules to embrace/respect: | Rules to embrace/respect: | ||
Line 46: | Line 60: | ||
# don't add features while you port to keep it understandable and revert-able. | # don't add features while you port to keep it understandable and revert-able. | ||
The component uses no header file (it is generated from IDL at compile time and is really verbose) so you also need to write it manually. header file [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/zimAccessor/zimAccessor.h?revision= | The component uses no header file (it is generated from IDL at compile time and is really verbose) so you also need to write it manually. Refer to example. | ||
=== Write a C++ program testing the C++ API === | |||
Instead of writing a program to test the features of the API, we should write unit tests but I have no prior experience with unit testing with C/C++ so I choose the loose way. | |||
Feel free to improve that. | |||
The idea here is just to make sure that all methods are available and working as expected. | |||
* C++ library [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/zimAccessor/zimAccessor.h?revision=2811&view=markup header file] | |||
* C++ tester [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/zimTester/zimTester.cpp?revision=2920&view=markup source] | |||
I'm not very proud of it, a lot of stuff are hard coded and while it gets a ZIM as argument, it expects the swahili zim to test everything. | |||
=== Write a C Wrapper around the C++ API === | |||
js-ctypes (and ctypes) only works with C code and not with C++. Because our code base is in C++ (for good reasons), we need to add a C layer to interface with the C++ library. | |||
This is done by creating a C++ library (exported as C) containing only functions which would each call the C++ API. | |||
We'll add a couple functions to create/destroy the instance of the C++ class and each function will accept a pointer to the instance as parameter. | |||
* C Wrapper [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/zimAccessor/ZimAccessorWrapper.cpp?revision=HEAD&view=markup example] | |||
* C wrapper header [http://kiwix.svn.sourceforge.net/viewvc/kiwix/moulinkiwix/src/zimAccessor/ZimAccessorWrapper.h?revision=HEAD&view=markup example] | |||
Rules: | |||
# Create a void pointer type to match the class pointer. | |||
# Create functions to crete/destroy the class instance. | |||
# All functions are prefixed with library name (and keep case) | |||
# All functions have previously created type as first argument | |||
# expect C types as input (''char *'') | |||
# convert ''char *'' to ''string'' inside your function | |||
# convert outputed ''string'' to ''char *'' | |||
# return the actual data. Most of the time, we only have one return variable. Use that as return type for the wrapper. It's easier and cleaner from the JS perspective. | |||
Header example | |||
<blockquote><source lang="cpp"> | |||
typedef void * HZIMCLASS; | |||
HIMCLASS ZimAccessor_Create( void ); | |||
void ZimAccessor_Destroy( HZIMCLASS h ); | |||
const char* ZimAccessor_GetPageUrlFromTitle( HZIMCLASS h, char* url); | |||
</source></blockquote> | |||
Source example | |||
<blockquote><source lang="cpp"> | |||
/* creates instance of ZimAccessor */ | |||
HZIMCLASS ZimAccessor_Create( void ) { | |||
ZimAccessor * zimAccessor = new ZimAccessor(0); | |||
// Return its pointer (opaque) | |||
return (HZIMCLASS)zimAccessor; | |||
} | |||
/* Delete instance of ZimAccessor */ | |||
void ZimAccessor_Destroy( HZIMCLASS h ) { | |||
assert(h != NULL); | |||
// Convert from handle to ZimAccessor pointer | |||
ZimAccessor * zimAccessor = (ZimAccessor *)h; | |||
delete zimAccessor; | |||
} | |||
/* Return a page url fronm title */ | |||
const char* ZimAccessor_GetPageUrlFromTitle( HZIMCLASS h, char* title) { | |||
assert(h != NULL); | |||
ZimAccessor * zimAccessor = (ZimAccessor *)h; | |||
string cptitle = string(title); | |||
string url = ""; | |||
zimAccessor->GetPageUrlFromTitle(cptitle, url); | |||
return url.c_str(); | |||
} | |||
</source></blockquote> | |||
== Tips == | |||
* .so libs in xulrunner folder | |||
== Remaining work == | == Remaining work == | ||
* unicode | * unicode | ||
* makefiles |
edits