diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 17:43:19 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 17:43:19 +0000 |
commit | 0292059f4a16434600564cfa3f0ad2309a508a54 (patch) | |
tree | d95953cd53011917c4df679b96aedca39401b54f /doc/html | |
download | libksquirrel-0292059f4a16434600564cfa3f0ad2309a508a54.tar.gz libksquirrel-0292059f4a16434600564cfa3f0ad2309a508a54.zip |
Added libksquirrel for KDE3
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/libksquirrel@1095624 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'doc/html')
-rw-r--r-- | doc/html/Makefile.am | 22 | ||||
-rw-r--r-- | doc/html/belka_bkgr.gif | bin | 0 -> 18507 bytes | |||
-rw-r--r-- | doc/html/bits.html | 44 | ||||
-rw-r--r-- | doc/html/development-highlev.html | 82 | ||||
-rw-r--r-- | doc/html/how_to_build_arrow.png | bin | 0 -> 4023 bytes | |||
-rw-r--r-- | doc/html/how_to_build_c++.png | bin | 0 -> 13939 bytes | |||
-rw-r--r-- | doc/html/how_to_build_c.png | bin | 0 -> 13747 bytes | |||
-rw-r--r-- | doc/html/how_to_build_codec.png | bin | 0 -> 12672 bytes | |||
-rw-r--r-- | doc/html/index.html | 26 | ||||
-rw-r--r-- | doc/html/ksquirrel-libs-about.html | 24 | ||||
-rw-r--r-- | doc/html/ksquirrel-libs-fio.html | 140 | ||||
-rw-r--r-- | doc/html/ksquirrel-libs-metainfo.html | 55 | ||||
-rw-r--r-- | doc/html/ksquirrel-libs-olibs.html | 28 | ||||
-rw-r--r-- | doc/html/ksquirrel-libs-olibs1.html | 129 | ||||
-rw-r--r-- | doc/html/ksquirrel-libs-olibs2.html | 1620 | ||||
-rw-r--r-- | doc/html/ksquirrel-libs-olibs3.html | 365 | ||||
-rw-r--r-- | doc/html/ksquirrel-libs-struct.html | 201 | ||||
-rw-r--r-- | doc/html/styles.css | 26 |
18 files changed, 2762 insertions, 0 deletions
diff --git a/doc/html/Makefile.am b/doc/html/Makefile.am new file mode 100644 index 0000000..b0951e0 --- /dev/null +++ b/doc/html/Makefile.am @@ -0,0 +1,22 @@ +EXTRA_DIST = belka_bkgr.gif how_to_build_c++.png ksquirrel-libs-olibs1.html bits.html index.html ksquirrel-libs-olibs2.html Makefile.am development-highlev.html ksquirrel-libs-about.html ksquirrel-libs-olibs2.html how_to_build_arrow.png ksquirrel-libs-fio.html ksquirrel-libs-olibs3.html how_to_build_codec.png ksquirrel-libs-olibs.html styles.css how_to_build_c.png ksquirrel-libs-metainfo.html ksquirrel-libs-struct.html + + +install-data-local: + $(mkinstalldirs) $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION) + $(INSTALL_DATA) index.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/index.html + $(INSTALL_DATA) bits.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/bits.html + $(INSTALL_DATA) development-highlev.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/development-highlev.html + $(INSTALL_DATA) ksquirrel-libs-about.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/ksquirrel-libs-about.html + $(INSTALL_DATA) ksquirrel-libs-fio.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/ksquirrel-libs-fio.html + $(INSTALL_DATA) ksquirrel-libs-metainfo.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/ksquirrel-libs-metainfo.html + $(INSTALL_DATA) ksquirrel-libs-struct.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/ksquirrel-libs-struct.html + $(INSTALL_DATA) ksquirrel-libs-olibs.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/ksquirrel-libs-olibs.html + $(INSTALL_DATA) ksquirrel-libs-olibs1.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/ksquirrel-libs-olibs1.html + $(INSTALL_DATA) ksquirrel-libs-olibs2.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/ksquirrel-libs-olibs2.html + $(INSTALL_DATA) ksquirrel-libs-olibs3.html $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/ksquirrel-libs-olibs3.html + $(INSTALL_DATA) styles.css $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/styles.css + $(INSTALL_DATA) belka_bkgr.gif $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/belka_bkgr.gif + $(INSTALL_DATA) how_to_build_c.png $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/how_to_build_c.png + $(INSTALL_DATA) how_to_build_c++.png $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/how_to_build_c++.png + $(INSTALL_DATA) how_to_build_codec.png $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/how_to_build_codec.png + $(INSTALL_DATA) how_to_build_arrow.png $(DESTDIR)$(datadir)/doc/ksquirrel-libs/$(PACKAGE_VERSION)/how_to_build_arrow.png diff --git a/doc/html/belka_bkgr.gif b/doc/html/belka_bkgr.gif Binary files differnew file mode 100644 index 0000000..75f5cb8 --- /dev/null +++ b/doc/html/belka_bkgr.gif diff --git a/doc/html/bits.html b/doc/html/bits.html new file mode 100644 index 0000000..d889727 --- /dev/null +++ b/doc/html/bits.html @@ -0,0 +1,44 @@ +<pre> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +int main(int argc, char **argv) +{ + int i; + for(i = 1;i < argc;i++) + { + FILE *f = fopen(argv[i], "rb"); + char c; + struct stat buf; + + if(!f) + { + fprintf(stderr, "Can't open file.\n"); + return 255; + } + + int s = 0, sz; + stat(argv[i], &buf); + + sz = buf.st_size; + + printf("%s\nstd::string fmt_codec::fmt_pixmap()\n{\n\treturn std::string(\"", argv[i]); + + while(s++ < sz-1) + { + fread(&c, 1, 1, f); + printf("%u,", (unsigned char)c); + } + + fread(&c, 1, 1, f); + printf("%u", (unsigned char)c); + + printf("\");\n}\n\n"); + fclose(f); + } + + return 0; +} +</pre>
\ No newline at end of file diff --git a/doc/html/development-highlev.html b/doc/html/development-highlev.html new file mode 100644 index 0000000..6174f5c --- /dev/null +++ b/doc/html/development-highlev.html @@ -0,0 +1,82 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta name='Author' content='Baryshev Dmitry/Krasu'> + <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'> + + <link rel='stylesheet' href='styles.css' type='text/css'> +</head> + +<body> + +When SQ_LibraryHandler loaded all found libraries, KSquirrel obtains the ability to decode any supported image format. +Here is a sample code to decode some image with library. Error handling is turned <b>off</b>. You can find real examples in +source distribution of ksquirrel-libs. + +<p><b><u>Sample</u></b> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> +<tbody> +<tr> +<td valign="top" bgcolor="#CCCCCC"> +<pre> + int i, j, current = 0; + fmt_info finfo; + RGBA *image = NULL, *scan; + fmt_codec_base *codeK; + + QString file = "/home/krasu/animation1.gif"; + + <b>Determine the library and codec</b> + codeK = SQ_LibraryHandler::instance()->libraryForFile(file)->codec; + + <b>Init: open file, etc.</b> + codeK->read_init(file.ascii()); + + while(true) + { + i = codeK->read_next(); + + <b>Break, if we've decoded all available images in file</b> + if(i == SQE_NOTOK) + break; + + <b>Obtain the latest information (current image dimensions, etc.)</b> + finfo = codeK->information(); + + <b>realloc memory for new image</b> + image = (RGBA *)realloc(image, finfo.image[current].w * finfo.image[current].h * sizeof(RGBA)); + + <b>fill with white color (RGBA(255,255,255,255))</b> + memset(image, 255, finfo.image[current].w * finfo.image[current].h * sizeof(RGBA)); + + for(int pass = 0;pass < finfo.image[current].passes;pass++) + { + codeK->read_next_pass(); + + for(j = 0;j < finfo.image[current].h;j++) + { + scan = image + j * finfo.image[current].w; + codeK->read_scanline(scan); + } + } + + <b>Do something with decoded image here. + ...</b> + + current++; + } + + codeK->read_close(); + + free(image); + +</pre> +</td> +</tr> +</tbody> +</table> + +</body> +</html> diff --git a/doc/html/how_to_build_arrow.png b/doc/html/how_to_build_arrow.png Binary files differnew file mode 100644 index 0000000..ff94733 --- /dev/null +++ b/doc/html/how_to_build_arrow.png diff --git a/doc/html/how_to_build_c++.png b/doc/html/how_to_build_c++.png Binary files differnew file mode 100644 index 0000000..3050def --- /dev/null +++ b/doc/html/how_to_build_c++.png diff --git a/doc/html/how_to_build_c.png b/doc/html/how_to_build_c.png Binary files differnew file mode 100644 index 0000000..2610b60 --- /dev/null +++ b/doc/html/how_to_build_c.png diff --git a/doc/html/how_to_build_codec.png b/doc/html/how_to_build_codec.png Binary files differnew file mode 100644 index 0000000..2348108 --- /dev/null +++ b/doc/html/how_to_build_codec.png diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..5726395 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta name='Author' content='Baryshev Dmitry/Krasu'> + <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'> + + <link rel='stylesheet' href='styles.css' type='text/css'> +</head> + +<body> + +<p>If you want to help to develop this project, please contact me by <a href='mailto:ksquirrel@tut.by'>e-mail</a>. +<p>Here you can find various information, concerning development KSquirrel and libraries ksquirrel-libs. +<p>All information listed below is valid for <b>v0.6.0-pre3</b> or later. + +<p><a href='ksquirrel-libs-about.html'>About ksquirrel-libs</a> +<p><a href='development-highlev.html'>How KSquirrel uses ksquirrel-libs</a> +<p><a href='ksquirrel-libs-olibs.html'>How to build libraries</a> +<p><a href='ksquirrel-libs-struct.html'>About typedefs in ksquirrel-libs</a> +<p><a href='ksquirrel-libs-metainfo.html'>Using metainfo mechanism</a> +<p><a href='ksquirrel-libs-fio.html'>Internal file i/o</a> + +</body> +</html> diff --git a/doc/html/ksquirrel-libs-about.html b/doc/html/ksquirrel-libs-about.html new file mode 100644 index 0000000..16668d7 --- /dev/null +++ b/doc/html/ksquirrel-libs-about.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name='Author' content='Baryshev Dmitry/Krasu'> + + <link rel="stylesheet" href="styles.css" type="text/css"> +</head> +<body> + +<p>ksquirrel-libs can be described in following terms: + +<p><ul> +<li>ksquirrel-libs is a set of codecs for the browser of images KSquirrel. +<li>format of libraries is very simple, so you can write the codec necessary to you. +<li>you can use ksquirrel-libs in your program - simply realize the mechanism, allowing to manipulate a set of such libraries (like SQ_LibraryHandler class in KSquirrel). +<li>each codec has a strictly defined set of functions which provide the interface of library. +<li>from the version 0.6.0-pre1 codecs are written on C++. +<li>from the point of view of C++ all codecs absolutely identical - they differ only with contents of methods. +</ul> +</body> +</html> diff --git a/doc/html/ksquirrel-libs-fio.html b/doc/html/ksquirrel-libs-fio.html new file mode 100644 index 0000000..2ead0b7 --- /dev/null +++ b/doc/html/ksquirrel-libs-fio.html @@ -0,0 +1,140 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name='Author' content='Baryshev Dmitry/Krasu'> + + <link rel="stylesheet" href="styles.css" type="text/css"> +</head> +<body> + +For reading and writing data I use the following classes, inherited from ifstream and ofstream. + +<table cellpadding="2" cellspacing="2" width="70%" align="center"> +<tbody> +<tr> +<td valign="top" bgcolor="#CCCCCC"> +<pre> +<b>Class for reading binary data</b> +class ifstreamK : public ifstream +{ + public: + ifstreamK(); + + <b>Read 'size' bytes of binary data and store it into 'data'. + Returns true if reading was successful, and false otherwise</b> + bool readK(void *data, int size); + + <b>Read string from file</b> + bool getS(char *, const int); + + <b>Read ascii hex value from file (like "0xFFFF00")</b> + bool readCHex(u32 &hex); + + <b>big-endian-oriented reading</b> + bool be_getchar(u8 *c); + bool be_getshort(u16 *s); + bool be_getlong(u32 *l); +}; + +<b>Class for writing binary data</b> +class ofstreamK : public ofstream +{ + public: + ofstreamK(); + + bool writeK(void *data, int size); +}; +</pre> +</td> +</tr> +</tbody> +</table> + +<b><u>Examples</u></b> + +<ul> +<li> Read structure from binary file +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> + typedef struct + { + int a; + short b; + char c; + + }Data; + + ... + + class::class() + { + fs.open("file.bin", ios::in | ios::binary); + } + + int class::readstruct(Data *s) + { + bool b = fs.readK(s, sizeof(Data)); + + cerr << "Reading " << (b ? "OK" : "Failed") << endl; + } + + </pre> + </td> + </tr> + </tbody> +</table> + +<br><br> +<li> Write structure to binary file +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> + typedef struct + { + int a; + short b; + char c; + + }Data; + + ... + + class::class() + { + fs.open("file.bin", ios::out | ios::binary); + } + + int class::writestruct(Data *s) + { + bool b = fs.writeK(s, sizeof(Data)); + + cerr << "Writing " << (b ? "OK" : "Failed") << endl; + } + + </pre> + </td> + </tr> + </tbody> +</table> + +<br> + +<b><u>Note:</u></b> remember, that reading and writing structures in binary mode is not doog idea. This is just example. See <a href='http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#7'>http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#7</a> and <a href='http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#3'>http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#3</a> for more. + +<br><br> + +</ul> +</body> +</html> diff --git a/doc/html/ksquirrel-libs-metainfo.html b/doc/html/ksquirrel-libs-metainfo.html new file mode 100644 index 0000000..2f5cf4d --- /dev/null +++ b/doc/html/ksquirrel-libs-metainfo.html @@ -0,0 +1,55 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name='Author' content='Baryshev Dmitry/Krasu'> + + <link rel="stylesheet" href="styles.css" type="text/css"> +</head> +<body> + +<p>For support of a metainformation, saved together with some images, in ksquirrel-libs exists the special +structure similar to map. Support of a metainformation COMPLETELY lays down on library i.e. +if in image file there are any collateral data, but library ignores it, +KSquirrel (as well as any other viewer on the basis of ksquirrel-libs) will not display it in +"Image Properties" dialog. + +<p>At present EXIF the information is not supported yet, but in v0.6.0 it possibly will be realized. +<p>Formally work with a metainformation looks so: [read some information from a file] => [group it] => [keep in object 'finfo']. Further you can see an example of the elementary reading and preservation of a metainformation. +<p>You should read metainfo in <b>fmt_read_next()</b> and store it in <b>finfo.meta</b>. + +<p> +<b><u>Example</u></b> + +<table cellpadding="2" cellspacing="2" width="70%" align="center"> +<tbody> +<tr> +<td valign="top" bgcolor="#CCCCCC"> +<pre> + <b>Read information from file</b> + frs.readK(str, 255); + + <b>Don't forget to insert '\0', if necessary</b> + str[255] = '\0'; + + fmt_metaentry mt; + + <b>Setup group name. It can be "JPEG "COM" Marker", "PNG key", + "SGI Image Name", or any other you want.</b> + mt.group = "Group name"; + + <b>Copy information</b> + mt.data = str; + + <b>insert new metaentry</b> + finfo.meta.push_back(mt); +</pre> +</td> +</tr> +</tbody> +</table> + +</body> +</html> diff --git a/doc/html/ksquirrel-libs-olibs.html b/doc/html/ksquirrel-libs-olibs.html new file mode 100644 index 0000000..915617b --- /dev/null +++ b/doc/html/ksquirrel-libs-olibs.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name='Author' content='Baryshev Dmitry/Krasu'> + + <link rel="stylesheet" href="styles.css" type="text/css"> +</head> +<body> + +Let's now learn how to create regular C or C++ library, and how to create a new decoder for KSquirrel. You can find sources of all examples in ksquirrel-libs/doc/sources. + +<p> + +<center> +<table> + <tr><td><a href="ksquirrel-libs-olibs1.html"><img src="how_to_build_c.png"></a></td></tr> + <tr><td align=center> <img src="how_to_build_arrow.png"></td></tr> + <tr><td><a href="ksquirrel-libs-olibs2.html"><img src="how_to_build_c++.png"></a></td></tr> + <tr><td align=center><img src="how_to_build_arrow.png"></td></tr> + <tr><td><a href="ksquirrel-libs-olibs3.html"><img src="how_to_build_codec.png"></a></td></tr> +</table> +</center> + +</body> +</html> diff --git a/doc/html/ksquirrel-libs-olibs1.html b/doc/html/ksquirrel-libs-olibs1.html new file mode 100644 index 0000000..1965e7d --- /dev/null +++ b/doc/html/ksquirrel-libs-olibs1.html @@ -0,0 +1,129 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name='Author' content='Baryshev Dmitry/Krasu'> + + <link rel="stylesheet" href="styles.css" type="text/css"> +</head> +<body> + +<ul> +<li>First, write regular C program (without main()): +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> + const char* fmt_info() + { + return "It is really cool format!"; + } + </pre> + </td> + </tr> + </tbody> +</table> +<br><br> +<li>Compile it +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> + # gcc -O2 -fPIC -c module.c + # gcc -shared -o module.so module.o + </pre> + </td> + </tr> + </tbody> +</table> +<br><br> +<li>Let's write a simple test +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> + #include <unistd.h> + #include <string.h> + #include <errno.h> + #include <dlfcn.h> + + #define PATH_LENGTH 256 + + int main(int argc, char * argv[]) + { + char path[PATH_LENGTH], *msg = NULL; + const char* (*fmt)(); + void *module; + + getcwd(path, PATH_LENGTH); + strcat(path, "/"); + strcat(path, "module.so"); + + /* Load module */ + module = dlopen(path, RTLD_NOW); + + /* Error ! */ + if(!module) + { + msg = dlerror(); + + if(msg != NULL) + { + dlclose(module); + exit(1); + } + } + + /* Try to resolve function "fmt_info()" */ + fmt = dlsym(module, "fmt_info"); + + msg = dlerror(); + + if(msg != NULL) + { + perror(msg); + dlclose(module); + exit(1); + } + + /* call fmt_info() through a pointer*/ + printf("%s\n", fmt()); + + /* close module */ + if(dlclose(module)) + { + perror("error"); + exit(1); + } + + return 0; + } + + # gcc -o test main.c -ldl + # ./test + It is really cool format! + # + + </pre> + </td> + </tr> + </tbody> +</table> +<br><br> +<li>That's all! :) Our test program has just loaded <u>module.so</u> and called <u>fmt_info()</u>, located in it. It is very simple, isn't ? +<br><br> +</ul> + +</body> +</html> diff --git a/doc/html/ksquirrel-libs-olibs2.html b/doc/html/ksquirrel-libs-olibs2.html new file mode 100644 index 0000000..710df8a --- /dev/null +++ b/doc/html/ksquirrel-libs-olibs2.html @@ -0,0 +1,1620 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name='Author' content='Baryshev Dmitry/Krasu'> + + <link rel="stylesheet" href="styles.css" type="text/css"> +</head> +<body> + +<DIV +CLASS="ARTICLE" +><DIV +CLASS="TITLEPAGE" +><H1 +CLASS="title" +><A +NAME="AEN2" +></A +>C++ dlopen mini HOWTO</H1 +><H3 +CLASS="author" +><A +NAME="AEN4" +>Aaron Isotton</A +></H3 +><DIV +CLASS="affiliation" +><DIV +CLASS="address" +><P +CLASS="address" +><TT +CLASS="email" +><<A +HREF="mailto:aaron@isotton.com" +>aaron@isotton.com</A +>></TT +></P +></DIV +></DIV +><P +CLASS="pubdate" +>2003-08-12<BR></P +><DIV +CLASS="revhistory" +><TABLE +WIDTH="100%" +BORDER="0" +><TR +><TH +ALIGN="LEFT" +VALIGN="TOP" +COLSPAN="3" +><B +>Revision History</B +></TH +></TR +><TR +><TD +ALIGN="LEFT" +>Revision 1.03</TD +><TD +ALIGN="LEFT" +>2003-08-12</TD +><TD +ALIGN="LEFT" +>Revised by: AI</TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +>Added reference to the GLib Dynamic Module + Loader. Thanks to G. V. Sriraam for the pointer.</TD +></TR +><TR +><TD +ALIGN="LEFT" +>Revision 1.02</TD +><TD +ALIGN="LEFT" +>2002-12-08</TD +><TD +ALIGN="LEFT" +>Revised by: AI</TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +>Added FAQ. Minor changes</TD +></TR +><TR +><TD +ALIGN="LEFT" +>Revision 1.01</TD +><TD +ALIGN="LEFT" +>2002-06-30</TD +><TD +ALIGN="LEFT" +>Revised by: AI</TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +>Updated virtual destructor explanation. Minor changes.</TD +></TR +><TR +><TD +ALIGN="LEFT" +>Revision 1.00</TD +><TD +ALIGN="LEFT" +>2002-06-19</TD +><TD +ALIGN="LEFT" +>Revised by: AI</TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +>Moved copyright and license section to the + beginning. Added terms section. Minor changes.</TD +></TR +><TR +><TD +ALIGN="LEFT" +>Revision 0.97</TD +><TD +ALIGN="LEFT" +>2002-06-19</TD +><TD +ALIGN="LEFT" +>Revised by: JYG</TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +>Entered minor grammar and sentence level changes.</TD +></TR +><TR +><TD +ALIGN="LEFT" +>Revision 0.96</TD +><TD +ALIGN="LEFT" +>2002-06-12</TD +><TD +ALIGN="LEFT" +>Revised by: AI</TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +>Added bibliography. Corrected explanation of extern + functions and variables.</TD +></TR +><TR +><TD +ALIGN="LEFT" +>Revision 0.95</TD +><TD +ALIGN="LEFT" +>2002-06-11</TD +><TD +ALIGN="LEFT" +>Revised by: AI</TD +></TR +><TR +><TD +ALIGN="LEFT" +COLSPAN="3" +>Minor improvements.</TD +></TR +></TABLE +></DIV +><DIV +><DIV +CLASS="abstract" +><A +NAME="AEN47" +></A +><P +></P +><P +>How to dynamically load C++ functions and classes using + the <TT +CLASS="function" +>dlopen</TT +> API.</P +><P +></P +></DIV +></DIV +><HR></DIV +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +>1. <A +HREF="#intro" +>Introduction</A +></DT +><DD +><DL +><DT +>1.1. <A +HREF="#copyright" +>Copyright and License</A +></DT +><DT +>1.2. <A +HREF="#disclaimer" +>Disclaimer</A +></DT +><DT +>1.3. <A +HREF="#credits" +>Credits / Contributors</A +></DT +><DT +>1.4. <A +HREF="#feedback" +>Feedback</A +></DT +><DT +>1.5. <A +HREF="#AEN85" +>Terms Used in this Document</A +></DT +></DL +></DD +><DT +>2. <A +HREF="#theproblem" +>The Problem</A +></DT +><DD +><DL +><DT +>2.1. <A +HREF="#mangling" +>Name Mangling</A +></DT +><DT +>2.2. <A +HREF="#AEN131" +>Classes</A +></DT +></DL +></DD +><DT +>3. <A +HREF="#thesolution" +>The Solution</A +></DT +><DD +><DL +><DT +>3.1. <A +HREF="#externC" +><TT +CLASS="literal" +>extern "C"</TT +></A +></DT +><DT +>3.2. <A +HREF="#loadingfunctions" +>Loading Functions</A +></DT +><DT +>3.3. <A +HREF="#loadingclasses" +>Loading Classes</A +></DT +></DL +></DD +><DT +>4. <A +HREF="#faq" +>Frequently Asked Questions</A +></DT +><DT +>5. <A +HREF="#seealso" +>See Also</A +></DT +><DT +><A +HREF="#AEN295" +>Bibliography</A +></DT +></DL +></DIV +><DIV +CLASS="section" +><H1 +CLASS="section" +><A +NAME="intro" +></A +>1. Introduction</H1 +><P +> A question which frequently arises among Unix C++ programmers is + how to load C++ functions and classes dynamically using the + <TT +CLASS="function" +>dlopen</TT +> API. + </P +><P +>In fact, that is not always simple and needs some + explanation. That's what this mini HOWTO does.</P +><P +>An average understanding of the <SPAN +CLASS="systemitem" +>C</SPAN +> + and <SPAN +CLASS="systemitem" +>C++</SPAN +> programming language and of the + <TT +CLASS="function" +>dlopen</TT +> API is necessary to understand this + document.</P +><P +>This HOWTO's master location is <A +HREF="http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/" +TARGET="_top" +>http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/</A +>.</P +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="copyright" +></A +>1.1. Copyright and License</H2 +><P +> This document, <EM +>C++ dlopen mini HOWTO</EM +>, is + copyrighted (c) 2002 by <EM +>Aaron Isotton</EM +>. + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation + License, Version 1.1 or any later version published by the + Free Software Foundation; with no Invariant Sections, with no + Front-Cover Texts, and with no Back-Cover Texts. + </P +></DIV +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="disclaimer" +></A +>1.2. Disclaimer</H2 +><P +> No liability for the contents of this document can be + accepted. Use the concepts, examples and information at your + own risk. There may be errors and inaccuracies, that could be + damaging to your system. Proceed with caution, and although + this is highly unlikely, the author(s) do not take any + responsibility. + </P +><P +> All copyrights are held by their by their respective owners, + unless specifically noted otherwise. Use of a term in this + document should not be regarded as affecting the validity of + any trademark or service mark. Naming of particular products + or brands should not be seen as endorsements. + </P +></DIV +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="credits" +></A +>1.3. Credits / Contributors</H2 +><P +> In this document, I have the pleasure of acknowledging (in + alphabetic order): + </P +><P +></P +><UL +><LI +><P +>Joy Y Goodreau <TT +CLASS="email" +><<A +HREF="mailto:joyg (at) us.ibm.com" +>joyg (at) us.ibm.com</A +>></TT +> for + her editing.</P +></LI +><LI +><P +>D. Stimitis <TT +CLASS="email" +><<A +HREF="mailto:stimitis (at) idcomm.com" +>stimitis (at) idcomm.com</A +>></TT +> + for pointing out a few issues with the formatting and the + name mangling, as well as pointing out a few subtleties of + <TT +CLASS="literal" +>extern "C"</TT +>.</P +></LI +></UL +></DIV +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="feedback" +></A +>1.4. Feedback</H2 +><P +> Feedback is most certainly welcome for this document. Send + your additions, comments and criticisms to the following email + address: <TT +CLASS="email" +><<A +HREF="mailto:aaron@isotton.com" +>aaron@isotton.com</A +>></TT +>. + </P +></DIV +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="AEN85" +></A +>1.5. Terms Used in this Document</H2 +><P +></P +><DIV +CLASS="variablelist" +><DL +><DT +><TT +CLASS="function" +>dlopen</TT +> API</DT +><DD +><P +>The <TT +CLASS="function" +>dlclose</TT +>, + <TT +CLASS="function" +>dlerror</TT +>, + <TT +CLASS="function" +>dlopen</TT +> and + <TT +CLASS="function" +>dlsym</TT +> functions as described in the + <TT +CLASS="literal" +>dlopen(3)</TT +> man page.</P +><P +>Notice that we use + <SPAN +CLASS="QUOTE" +>"<TT +CLASS="function" +>dlopen</TT +>"</SPAN +> to refer to + the individual <TT +CLASS="function" +>dlopen</TT +> + <EM +>function</EM +>, and + <SPAN +CLASS="QUOTE" +>"<TT +CLASS="function" +>dlopen</TT +> API"</SPAN +> to refer + to the <EM +>entire API</EM +>.</P +></DD +></DL +></DIV +></DIV +></DIV +><DIV +CLASS="section" +><HR><H1 +CLASS="section" +><A +NAME="theproblem" +></A +>2. The Problem</H1 +><P +>At some time you might have to load a library (and use its + functions) at runtime; this happens most often when you are + writing some kind of plug-in or module architecture for your + program.</P +><P +>In the C language, loading a library is very simple (calling + <TT +CLASS="function" +>dlopen</TT +>, <TT +CLASS="function" +>dlsym</TT +> and + <TT +CLASS="function" +>dlclose</TT +> is enough), with C++ this is a bit + more complicated. The difficulties of loading a C++ library + dynamically are partially due to <A +HREF="#mangling" +>name + mangling</A +>, and partially due to the fact that the + <TT +CLASS="function" +>dlopen</TT +> API was written with C in mind, thus + not offering a suitable way to load classes.</P +><P +>Before explaining how to load libraries in C++, let's better + analyze the problem by looking at name mangling in more + detail. I recommend you read the explanation of name mangling, + even if you're not interested in it because it will help you + understanding why problems occur and how to solve them.</P +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="mangling" +></A +>2.1. Name Mangling</H2 +><P +>In every C++ program (or library, or object file), all + non-static functions are represented in the binary file as + <EM +>symbols</EM +>. These symbols are special text + strings that uniquely identify a function in the program, + library, or object file.</P +><P +>In C, the symbol name is the same as the function name: + the symbol of <TT +CLASS="function" +>strcpy</TT +> will be + <TT +CLASS="computeroutput" +>strcpy</TT +>, and so on. This is + possible because in C no two non-static functions can have the + same name.</P +><P +>Because C++ allows overloading (different functions with + the same name but different arguments) and has many features C + does not — like classes, member functions, exception + specifications — it is not possible to simply use the + function name as the symbol name. To solve that, C++ uses + so-called <EM +>name mangling</EM +>, which transforms + the function name and all the necessary information (like the + number and size of the arguments) into some weird-looking + string which only the compiler knows about. The mangled name + of <TT +CLASS="function" +>foo</TT +> might look like + <TT +CLASS="computeroutput" +>foo@4%6^</TT +>, for example. Or it + might not even contain the word <SPAN +CLASS="QUOTE" +>"foo"</SPAN +>.</P +><P +> One of the problems with name mangling is that the C++ + standard (currently [<SPAN +CLASS="citation" +>ISO14882</SPAN +>]) does not + define how names have to be mangled; thus every compiler + mangles names in its own way. Some compilers even change their + name mangling algorithm between different versions (notably + g++ 2.x and 3.x). Even if you worked out how your particular + compiler mangles names (and would thus be able to load + functions via <TT +CLASS="function" +>dlsym</TT +>), this would most + probably work with your compiler only, and might already be + broken with the next version.</P +></DIV +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="AEN131" +></A +>2.2. Classes</H2 +><P +>Another problem with the <TT +CLASS="function" +>dlopen</TT +> API + is the fact that it only supports loading + <EM +>functions</EM +>. But in C++ a library often + exposes a class which you would like to use in your + program. Obviously, to use that class you need to create an + instance of it, but that cannot be easily done.</P +></DIV +></DIV +><DIV +CLASS="section" +><HR><H1 +CLASS="section" +><A +NAME="thesolution" +></A +>3. The Solution</H1 +><DIV +CLASS="section" +><H2 +CLASS="section" +><A +NAME="externC" +></A +>3.1. <TT +CLASS="literal" +>extern "C"</TT +></H2 +><P +>C++ has a special keyword to declare a function with C + bindings: <TT +CLASS="literal" +>extern "C"</TT +>. A function declared + as <TT +CLASS="literal" +>extern "C"</TT +> uses the function name as + symbol name, just as a C function. For that reason, only + non-member functions can be declared as <TT +CLASS="literal" +>extern + "C"</TT +>, and they cannot be overloaded.</P +><P +>Although there are severe limitations, <TT +CLASS="literal" +>extern + "C"</TT +> functions are very useful because they can be + dynamically loaded using <TT +CLASS="function" +>dlopen</TT +> just like + a C function.</P +><P +>This does <EM +>not</EM +> mean that functions + qualified as <TT +CLASS="literal" +>extern "C"</TT +> cannot contain C++ + code. Such a function is a full-featured C++ function which + can use C++ features and take any type of argument.</P +></DIV +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="loadingfunctions" +></A +>3.2. Loading Functions</H2 +><P +>In C++ functions are loaded just like in C, with + <TT +CLASS="function" +>dlsym</TT +>. The functions you want to load + must be qualified as <TT +CLASS="literal" +>extern "C"</TT +> to avoid + the symbol name being mangled.</P +><DIV +CLASS="example" +><A +NAME="AEN156" +></A +><P +><B +>Example 1. Loading a Function</B +></P +><P +>main.cpp:</P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>#include <iostream> +#include <dlfcn.h> + + +int main() { + using std::cout; + using std::cerr; + + cout << "C++ dlopen demo\n\n"; + + // open the library + cout << "Opening hello.so...\n"; + void* handle = dlopen("./hello.so", RTLD_LAZY); + + if (!handle) { + cerr << "Cannot open library: " << dlerror() << '\n'; + return 1; + } + + // load the symbol + cout << "Loading symbol hello...\n"; + typedef void (*hello_t)(); + hello_t hello = (hello_t) dlsym(handle, "hello"); + if (!hello) { + cerr << "Cannot load symbol 'hello': " << dlerror() << + '\n'; + dlclose(handle); + return 1; + } + + // use it to do the calculation + cout << "Calling hello...\n"; + hello(); + + // close the library + cout << "Closing library...\n"; + dlclose(handle); +} +</PRE +></FONT +></TD +></TR +></TABLE +><P +>hello.cpp:</P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>#include <iostream> + +extern "C" void hello() { + std::cout << "hello" << '\n'; +} +</PRE +></FONT +></TD +></TR +></TABLE +></DIV +><P +>The function <TT +CLASS="function" +>hello</TT +> is defined in + <TT +CLASS="filename" +>hello.cpp</TT +>as <TT +CLASS="literal" +>extern + "C"</TT +>; it is loaded in <TT +CLASS="filename" +>main.cpp</TT +> + with the <TT +CLASS="function" +>dlsym</TT +> call. The function must be + qualified as <TT +CLASS="literal" +>extern "C"</TT +> because otherwise + we wouldn't know its symbol name.</P +><DIV +CLASS="warning" +><P +></P +><TABLE +CLASS="warning" +WIDTH="100%" +BORDER="0" +><TR +><TD +WIDTH="25" +ALIGN="CENTER" +VALIGN="TOP" +><IMG +SRC="../images/warning.gif" +HSPACE="5" +ALT="Warning"></TD +><TD +ALIGN="LEFT" +VALIGN="TOP" +><P +>There are two different forms of the + <TT +CLASS="literal" +>extern "C"</TT +> declaration: <TT +CLASS="literal" +>extern + "C"</TT +> as used above, and <TT +CLASS="literal" +>extern "C" { + … }</TT +> with the declarations between the + braces. The first (inline) form is a declaration with extern + linkage and with C language linkage; the second only affects + language linkage. The following two declarations are thus + equivalent: + + <DIV +CLASS="informalexample" +><A +NAME="AEN174" +></A +><P +></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>extern "C" int foo; +extern "C" void bar(); + </PRE +></FONT +></TD +></TR +></TABLE +><P +></P +></DIV +> + and + <DIV +CLASS="informalexample" +><A +NAME="AEN176" +></A +><P +></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>extern "C" { + extern int foo; + extern void bar(); + }</PRE +></FONT +></TD +></TR +></TABLE +><P +></P +></DIV +> + + As there is no difference between an + <TT +CLASS="literal" +>extern</TT +> and a + non-<TT +CLASS="literal" +>extern</TT +> <EM +>function</EM +> + declaration, this is no problem as long as you are not + declaring any variables. If you declare + <EM +>variables</EM +>, keep in mind that + + <DIV +CLASS="informalexample" +><A +NAME="AEN182" +></A +><P +></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>extern "C" int foo;</PRE +></FONT +></TD +></TR +></TABLE +><P +></P +></DIV +> + and + <DIV +CLASS="informalexample" +><A +NAME="AEN184" +></A +><P +></P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>extern "C" { + int foo; +}</PRE +></FONT +></TD +></TR +></TABLE +><P +></P +></DIV +> + + are <EM +>not</EM +> the same thing.</P +><P +>For further clarifications, refer to + [<SPAN +CLASS="citation" +>ISO14882</SPAN +>], 7.5, with special attention + to paragraph 7, or to [<SPAN +CLASS="citation" +>STR2000</SPAN +>], + paragraph 9.2.4.</P +><P +>Before doing fancy things with extern variables, peruse + the documents listed in the <A +HREF="#seealso" +>see + also</A +> section.</P +></TD +></TR +></TABLE +></DIV +></DIV +><DIV +CLASS="section" +><HR><H2 +CLASS="section" +><A +NAME="loadingclasses" +></A +>3.3. Loading Classes</H2 +><P +>Loading classes is a bit more difficult because we need + an <EM +>instance</EM +> of a class, not just a + pointer to a function.</P +><P +>We cannot create the instance of the class using + <TT +CLASS="literal" +>new</TT +> because the class is not defined in the + executable, and because (under some circumstances) we don't + even know its name.</P +><P +>The solution is achieved through polymorphism. We define a + base, <EM +>interface</EM +> class with virtual + members <EM +>in the executable</EM +>, and a derived, + <EM +>implementation</EM +> class <EM +>in the + module</EM +>. Generally the interface class is + abstract (a class is abstract if it has pure virtual + functions).</P +><P +>As dynamic loading of classes is generally used for + plug-ins — which must expose a clearly defined interface + — we would have had to define an interface and derived + implementation classes anyway.</P +><P +>Next, while still in the module, we define two additional helper + functions, known as <EM +>class factory + functions</EM +>. One of these functions creates an instance of the + class and returns a pointer to it. The other function takes a + pointer to a class created by the factory and destroys + it. These two functions are qualified as <TT +CLASS="literal" +>extern + "C"</TT +>.</P +><P +>To use the class from the module, load the two factory + functions using <TT +CLASS="function" +>dlsym</TT +> just <A +HREF="#loadingfunctions" +>as we loaded the the hello + function</A +>; then, we can create and destroy as many + instances as we wish.</P +><DIV +CLASS="example" +><A +NAME="AEN210" +></A +><P +><B +>Example 2. Loading a Class</B +></P +><P +>Here we use a generic <TT +CLASS="classname" +>polygon</TT +> + class as interface and the derived class + <TT +CLASS="classname" +>triangle</TT +> as implementation.</P +><P +>main.cpp:</P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>#include "polygon.hpp" +#include <iostream> +#include <dlfcn.h> + +int main() { + using std::cout; + using std::cerr; + + // load the triangle library + void* triangle = dlopen("./triangle.so", RTLD_LAZY); + if (!triangle) { + cerr << "Cannot load library: " << dlerror() << '\n'; + return 1; + } + + // load the symbols + create_t* create_triangle = (create_t*) dlsym(triangle, "create"); + destroy_t* destroy_triangle = (destroy_t*) dlsym(triangle, "destroy"); + if (!create_triangle || !destroy_triangle) { + cerr << "Cannot load symbols: " << dlerror() << '\n'; + return 1; + } + + // create an instance of the class + polygon* poly = create_triangle(); + + // use the class + poly->set_side_length(7); + cout << "The area is: " << poly->area() << '\n'; + + // destroy the class + destroy_triangle(poly); + + // unload the triangle library + dlclose(triangle); +} +</PRE +></FONT +></TD +></TR +></TABLE +><P +>polygon.hpp:</P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>#ifndef POLYGON_HPP +#define POLYGON_HPP + +class polygon { +protected: + double side_length_; + +public: + polygon() + : side_length_(0) {} + + void set_side_length(double side_length) { + side_length_ = side_length; + } + + virtual double area() const = 0; +}; + +// the types of the class factories +typedef polygon* create_t(); +typedef void destroy_t(polygon*); + +#endif +</PRE +></FONT +></TD +></TR +></TABLE +><P +>triangle.cpp:</P +><TABLE +BORDER="0" +BGCOLOR="#E0E0E0" +WIDTH="100%" +><TR +><TD +><FONT +COLOR="#000000" +><PRE +CLASS="programlisting" +>#include "polygon.hpp" +#include <cmath> + +class triangle : public polygon { +public: + virtual double area() const { + return side_length_ * side_length_ * sqrt(3) / 2; + } +}; + + +// the class factories + +extern "C" polygon* create() { + return new triangle; +} + +extern "C" void destroy(polygon* p) { + delete p; +} +</PRE +></FONT +></TD +></TR +></TABLE +></DIV +><P +>There are a few things to note when loading classes:</P +><P +></P +><UL +><LI +><P +>You must provide <EM +>both</EM +> a creation + and a destruction function; you must + <EM +>not</EM +> destroy the instances using + <TT +CLASS="literal" +>delete</TT +> from inside the executable, but + always pass it back to the module. This is due to the fact + that in C++ the operators <TT +CLASS="literal" +>new</TT +> and + <TT +CLASS="literal" +>delete</TT +> may be overloaded; this would + cause a non-matching <TT +CLASS="literal" +>new</TT +> and + <TT +CLASS="literal" +>delete</TT +> to be called, which could cause + anything from nothing to memory leaks and segmentation + faults. The same is true if different standard libraries + are used to link the module and the executable.</P +></LI +><LI +><P +>The destructor of the interface class should be + virtual in any case. There <EM +>might</EM +> be + very rare cases where that would not be necessary, but it + is not worth the risk, because the additional overhead can + generally be ignored.</P +><P +>If your base class needs no destructor, define an + empty (and <TT +CLASS="literal" +>virtual</TT +>) one anyway; + otherwise you <EM +>will have problems</EM +> + sooner or later; I can guarantee you that. You can read + more about this problem in the comp.lang.c++ FAQ at <A +HREF="http://www.parashift.com/c++-faq-lite/" +TARGET="_top" +>http://www.parashift.com/c++-faq-lite/</A +>, in + section 20.</P +></LI +></UL +></DIV +></DIV +><DIV +CLASS="section" +><HR><H1 +CLASS="section" +><A +NAME="faq" +></A +>4. Frequently Asked Questions</H1 +><DIV +CLASS="qandaset" +><DL +><DT +>4.1. <A +HREF="#AEN243" +>I'm using Windows and I can't find the + <TT +CLASS="filename" +>dlfcn.h</TT +> header file on my PC! What's + the problem?</A +></DT +><DT +>4.2. <A +HREF="#AEN257" +>Is there some kind of <TT +CLASS="function" +>dlopen</TT +>-compatible + wrapper for the Windows <TT +CLASS="function" +>LoadLibrary</TT +> + API?</A +></DT +></DL +><DIV +CLASS="qandaentry" +><DIV +CLASS="question" +><P +><A +NAME="AEN243" +></A +><B +>4.1. </B +>I'm using Windows and I can't find the + <TT +CLASS="filename" +>dlfcn.h</TT +> header file on my PC! What's + the problem?</P +></DIV +><DIV +CLASS="answer" +><P +><B +> </B +>The problem is, as usual, Windows. There is no + <TT +CLASS="filename" +>dlfcn.h</TT +> header on Windows,and there is + no <TT +CLASS="function" +>dlopen</TT +> API. There is a similar API + around the <TT +CLASS="function" +>LoadLibrary</TT +> function, and + most of what is written here applies to it, too. + Alternatively, you can use libltdl (included in libtool) to + <SPAN +CLASS="QUOTE" +>"emulate"</SPAN +> <TT +CLASS="function" +>dlopen</TT +> on a + variety of platforms.</P +><P +>You should also read section 4, <SPAN +CLASS="QUOTE" +>"Dynamically + Loaded (DL) Libraries"</SPAN +>, of the <A +HREF="http://www.dwheeler.com/program-library" +TARGET="_top" +>Program Library + HOWTO</A +> for more techniques to load libraries and + create classes independently of your platform.</P +></DIV +></DIV +><DIV +CLASS="qandaentry" +><DIV +CLASS="question" +><P +><A +NAME="AEN257" +></A +><B +>4.2. </B +>Is there some kind of <TT +CLASS="function" +>dlopen</TT +>-compatible + wrapper for the Windows <TT +CLASS="function" +>LoadLibrary</TT +> + API?</P +></DIV +><DIV +CLASS="answer" +><P +><B +> </B +>I don't know of any, and I don't think there'll ever be one + supporting all of <TT +CLASS="function" +>dlopen</TT +>'s options.</P +><P +>There are alternatives though: libtltdl (a part of libtool), + which wraps a variety of different dynamic loading APIs, among + others <TT +CLASS="function" +>dlopen</TT +> and + <TT +CLASS="function" +>LoadLibrary</TT +>. Another one is the <A +HREF="http://developer.gnome.org/doc/API/glib/glib-dynamic-loading-of-modules.html" +TARGET="_top" +>Dynamic + Module Loading functionality of GLib</A +>. You can use one + of these to ensure better possible cross-platform compatibility. + I've never used any of them, so I can't tell you how stable they + are and whether they really work.</P +></DIV +></DIV +></DIV +></DIV +><DIV +CLASS="section" +><HR><H1 +CLASS="section" +><A +NAME="seealso" +></A +>5. See Also</H1 +><P +></P +><UL +><LI +><P +>The <TT +CLASS="function" +>dlopen(3)</TT +> man page. It explains + the purpose and the use of the <TT +CLASS="function" +>dlopen</TT +> + API.</P +></LI +><LI +><P +>The article <A +HREF="http://www.linuxjournal.com/article.php?sid=3687" +TARGET="_top" +> <I +CLASS="citetitle" +>Dynamic Class Loading for C++ on + Linux</I +></A +> by James Norton published on the + <A +HREF="http://www.linuxjournal.com/" +TARGET="_top" +>Linux + Journal</A +>.</P +></LI +><LI +><P +>Your favorite C++ reference about <TT +CLASS="literal" +>extern + "C"</TT +>, inheritance, virtual functions, + <TT +CLASS="literal" +>new</TT +> and <TT +CLASS="literal" +>delete</TT +>. I + recommend [<SPAN +CLASS="citation" +>STR2000</SPAN +>].</P +></LI +><LI +><P +>[<SPAN +CLASS="citation" +>ISO14882</SPAN +>]</P +></LI +><LI +><P +>The <A +HREF="http://www.dwheeler.com/program-library" +TARGET="_top" +>Program Library + HOWTO</A +>, which tells you most things you'll ever need + about static, shared and dynamically loaded libraries and how + to create them. Highly recommended.</P +></LI +><LI +><P +>The <A +HREF="http://tldp.org/HOWTO/GCC-HOWTO/index.html" +TARGET="_top" +>Linux GCC + HOWTO</A +> to learn more about how to create libraries + with GCC.</P +></LI +></UL +></DIV +><A +NAME="AEN295" +></A +><HR><H1 +><A +NAME="AEN295" +></A +>Bibliography</H1 +><DIV +CLASS="bibliomixed" +><A +NAME="AEN296" +></A +><P +CLASS="bibliomixed" +> ISO14482 <I +>ISO/IEC 14482-1998 — The + C++ Programming Language</I +>. Available as + PDF and as printed book from <A +HREF="http://webstore.ansi.org/" +TARGET="_top" +>http://webstore.ansi.org/</A +>. + </P +></DIV +><DIV +CLASS="bibliomixed" +><A +NAME="AEN301" +></A +><P +CLASS="bibliomixed" +> STR2000 + <SPAN +CLASS="AUTHOR" +>Bjarne Stroustrup</SPAN +> + <I +>The C++ Programming Language</I +>, Special + Edition. + ISBN 0-201-70073-5. + Addison-Wesley. + </P +></DIV +></DIV +> + +</body> +</html> diff --git a/doc/html/ksquirrel-libs-olibs3.html b/doc/html/ksquirrel-libs-olibs3.html new file mode 100644 index 0000000..46150ec --- /dev/null +++ b/doc/html/ksquirrel-libs-olibs3.html @@ -0,0 +1,365 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name='Author' content='Baryshev Dmitry/Krasu'> + + <link rel="stylesheet" href="styles.css" type="text/css"> +</head> +<body> + +<center><h3><b>How to write a new library for KSquirrel (for example, it will decode abstract 'ttx' format) ?</b></h3></center> + +<ul> +<li>Create a directory with necessary sources ('generate' is distributed with ksquirrel-libs): +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> +# ./generate ttx -build + </pre> + </td> + </tr> + </tbody> +</table> +<br><br> +<li>Typical fmt_codec_ttx_defs.h +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> +#ifndef KSQUIRREL_READ_IMAGE_ttx +#define KSQUIRREL_READ_IMAGE_ttx + +// Define constants you need here + +#endif + </pre> + </td> + </tr> + </tbody> +</table> +<br><br> +<li>Typical fmt_codec_ttx.h +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> +#ifndef KSQUIRREL_LIBS_CLASS_DEFINITION_ttx_H +#define KSQUIRREL_LIBS_CLASS_DEFINITION_ttx_H + +#include "fmt_codec_base.h" + +class fmt_codec : public fmt_codec_base +{ + public: + + fmt_codec(); + ~fmt_codec(); + + virtual std::string fmt_version(); + virtual std::string fmt_quickinfo(); + virtual std::string fmt_filter(); + virtual std::string fmt_mime(); + virtual std::string fmt_pixmap(); + virtual std::string fmt_extension(const s32 bpp); + + virtual bool fmt_readable() const; + virtual s32 fmt_read_init(const std::string &file); + virtual s32 fmt_read_next(); + virtual s32 fmt_read_next_pass(); + virtual s32 fmt_read_scanline(RGBA *scan); + virtual void fmt_read_close(); + + + virtual bool fmt_writable() const; + virtual void fmt_getwriteoptions(fmt_writeoptionsabs *); + virtual s32 fmt_write_init(const std::string &file, const fmt_image &image, + const fmt_writeoptions &opt); + virtual s32 fmt_write_next(); + virtual s32 fmt_write_next_pass(); + virtual s32 fmt_write_scanline(RGBA *scan); + virtual void fmt_write_close(); + + private: + // define variables you need here +}; + +extern "C" fmt_codec_base* fmt_codec_create() +{ + return (new fmt_codec); +} + +extern "C" void fmt_codec_destroy(fmt_codec_base *p) +{ + delete p; +} +</pre> + </td> + </tr> + </tbody> +</table> +<br><br> +<li>Typical fmt_codec_ttx.cpp +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + + <pre> + +#include <iostream> + +#include "fmt_types.h" +#include "fileio.h" +#include "fmt_codec_ttx_defs.h" +#include "fmt_codec_ttx.h" + +#include "error.h" + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +<b>Returns library's version</b> +std::string fmt_codec::fmt_version() +{ + return std::string("0.0.1"); +} + +<b>Returns common information on ttx format</b> +std::string fmt_codec::fmt_quickinfo() +{ + return std::string("TTX is a very cool format!"); +} + +<b>Filter for a file manager (with a blank after +each extension)</b> +std::string fmt_codec::fmt_filter() +{ + return std::string("*.ttx1 *.ttx2 *.ttx3 "); +} + +<b>The regular expression defining the file type +(usually first 2-5 characters in a file). +This example shows, that format TTX is defined by header +TTX7, TTX8 or TTX9. If the file has no header + (like .ico and .pix) this function should return empty string.</b> +std::string fmt_codec::fmt_mime() +{ + return std::string("TTX[789]"); +} + +<b>Compile <a href='bits.html'>this program</a>, +create PNG icon 16x16 and run +#./bits icon.png > icon.bits. +Then copy contents of icon.bits here</b> +std::string fmt_codec::fmt_pixmap() +{ + return std::string(""); +} + +<b>Open file, initialize variables, etc.</b> +s32 fmt_codec::fmt_read_init(const std::string &file) +{ + frs.open(file.c_str(), ios::binary | ios::in); + + if(!frs.good()) + return SQERR_NOFILE; + + currentImage = -1; + read_error = false; + + finfo.animated = false; + + return SQERR_OK; +} + +<b>This method will be called BEFORE decoding of each image in a file, +so we should seek to correct file offset or do something important now. +Return SQERR_NOTOK, if the next image can't be decoded (no such image), +and any other error code on error.</b> +s32 fmt_codec::fmt_read_next() +{ + currentImage++; + + if(currentImage) + return SQERR_NOTOK; <b>return, if TTX can + have only one image.</b> + + fmt_image image; + + <b>Non-interlaced image has 1 pass. + If you need to define another value, do it here</b> + image.passes = 1; + +<b>Here you should read necessary data from file, +and initialize finfo.image[currentImage].w,h,bpp. Return error +code you need on error.</b> +<b>...</b> + + image.compression = "-"; + image.colorspace = "RGB"; + + finfo.image.push_back(image); + + return SQERR_OK; +} + +<b>This method will be called BEFORE decoding of each pass +in the interlaced image.</b> +s32 fmt_codec::fmt_read_next_pass() +{ + <b>Our TTX fromat can't be interlaced, so we + won't do anything, just return SQERR_OK</b> + return SQERR_OK; +} + +<b>Reads scanline in 'scan'. This example just fills +'scan' with white color (RGBA(255,255,255,255))</b> +s32 fmt_codec::fmt_read_scanline(RGBA *scan) +{ + memset(scan, 255, finfo.image[currentImage].w * sizeof(RGBA)); + + return SQERR_OK; +} + +<b>Closes everything, frees allocated memory, etc.</b> +void fmt_codec::fmt_read_close() +{ + frs.close(); + + // you should free information on close + finfo.meta.clear(); + finfo.image.clear(); +} + +<b>Returns write options for TTX format. This method won't be +called, if fmt_writable() returns 'false'</b> +void fmt_codec::fmt_getwriteoptions(fmt_writeoptionsabs *opt) +{ + <b>Can TTX format be interlaced ? No.</b> + opt->interlaced = false; + + <b>With which compression it can be compressed ? + With no compression (like not-RLE BMP).</b> + opt->compression_scheme = CompressionNo; + + <b>minimum, maximum, and default compression level. + Ignored, if the compression is CompressionNo.</b> + opt->compression_min = 0; + opt->compression_max = 0; + opt->compression_def = 0; + + <b>TTX can't be interlaced, passes = 1</b> + opt->passes = 1; + + <b>KSquirrel shouldn't flip the image + before writing</b> + opt->needflip = false; +} + +<b>Same to fmt_read_init()</b> +s32 fmt_codec::fmt_write_init(const std::string &file, const fmt_image &image, + const fmt_writeoptions &opt) +{ + if(!image.w || !image.h || file.empty()) + return SQE_W_WRONGPARAMS; + + writeimage = image; + writeopt = opt; + + fws.open(file.c_str(), ios::binary | ios::out); + + if(!fws.good()) + return SQE_W_NOFILE; + + return SQE_OK; +} + +<b>Same to fmt_read_next()</b> +s32 fmt_codec::fmt_write_next() +{ + return SQE_OK; +} + +<b>Same to fmt_read_next_pass()</b> +s32 fmt_codec::fmt_write_next_pass() +{ + return SQE_OK; +} + +<b>Write scanline. Same to fmt_read_scanline()</b> +s32 fmt_codec::fmt_write_scanline(RGBA *scan) +{ + ... + return SQE_OK; +} + +<b>Same to fmt_read_init()</b> +void fmt_codec::fmt_write_close() +{ + fws.close(); +} + +<b>Can this library write TTX ? No.</b> +bool fmt_codec::fmt_writable() const +{ + return false; +} + +<b>Can this library read TTX ? Yes.</b> +bool fmt_codec::fmt_readable() const +{ + return true; +} + +<b>Some libraries support several image types (like PNM library). +This method should be used by writing function to determine file extension by image's bpp. +For example, 1 bpp means .pbm, 8 bpp - pgm</b>" +std::string fmt_codec::fmt_extension(const s32 /*bpp*/) +{ + return std::string(""); +} + + </pre> + </td> + </tr> + </tbody> +</table> +<br><br> +<li>Compile it +<br><br> +<table cellpadding="2" cellspacing="2" width="70%" align="center"> + <tbody> + <tr> + <td valign="top" bgcolor="#CCCCCC"> + <pre> +# ./compile-c++ +# + </pre> + </td> + </tr> + </tbody> +</table> + +<br><br> +<li>That's all. You've just created a new decoder for KSquirrel. Copy libSQ_codec_ttx.so in /usr/lib/ksquirrel-libs. +</ul> + +</body> +</html> diff --git a/doc/html/ksquirrel-libs-struct.html b/doc/html/ksquirrel-libs-struct.html new file mode 100644 index 0000000..154d1d5 --- /dev/null +++ b/doc/html/ksquirrel-libs-struct.html @@ -0,0 +1,201 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> +<head> + <title>KSquirrel: development</title> + + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <meta name='Author' content='Baryshev Dmitry/Krasu'> + + <link rel="stylesheet" href="styles.css" type="text/css"> +</head> +<body> + +In ksquirrel-libs I use the following wrappers for built-in types (valid for x86, 32-bit platform): int - <b>s32</b>, +unsigned int - <b>u32</b>, short - <b>s16</b>, unsigned short - <b>u16</b>, char - <b>s8</b>, unsinged char - <b>u8</b>. +All of them are defined in <b>fmt_types.h</b>. + +<pre> +<b>Defines one metainfo record. For example: + {"JPEG 'COM' marker", "File written by Photoshop"}</b> +struct fmt_metaentry +{ + <b>Group name, for example "SGI Image name"</b> + std::string group; + + <b>Information. For example "This image was created with MegaTool 0.5.1"</b> + std::string data; + +}; + +<b>Defines 32-bit pixel. Red, Green, Blue and Alpha channel.</b> +struct RGBA +{ + RGBA() : r(0), g(0), b(0), a(0) + {} + + RGBA(s32 r1, s32 g1, s32 b1, s32 a1) : r(r1), g(g1), b(b1), a(a1) + {} + + u8 r; + u8 g; + u8 b; + u8 a; +}PACKED; + +<b>Defines 24-bit color pixel. Red, Green, Blue.</b> +struct RGB +{ + RGB() : r(0), g(0), b(0) + {} + + RGB(s32 r1, s32 g1, s32 b1) : r(r1), g(g1), b(b1) + {} + + u8 r; + u8 g; + u8 b; + +}PACKED; + +<b>Defines one image. It stores the main information about one image: width, +height, metainfo, ...</b> +struct fmt_image +{ + fmt_image() : w(0), h(0), bpp(0), hasalpha(false), needflip(false), + delay(0), interlaced(false), passes(1) + {} + + <b>width of the image</b> + s32 w; + <b>height</b> + s32 h; + <b>bits per pixel</b> + s32 bpp; + <b>has alpha channel ?</b> + bool hasalpha; + <b>flip ? (for example BMP needs)</b> + bool needflip; + <b>only for animated images (like GIF)</b> + s32 delay; + <b>Is it interlaced or normal ?</b> + bool interlaced; + <b>Item 'passes' stores a number of passes if the image is iterlaced, or 1 otherwise.</b> + s32 passes; + <b>color space (RGB, RGBA, CMYK, LAB ...)</b> + std::string colorspace; + <b>compression type (RLE, JPEG, Deflate ...)</b> + std::string compression; + +}; + +<b>The main structure in ksquirrel-libs. It contains all information needed +to decode a file with one or more images.</b> +struct fmt_info +{ + fmt_info() : animated(false) + {} + + <b>Array of fmt_image structures. One structure defines one image.</b> + std::vector<fmt_image> image; + + <b>Metainfo entries</b> + std::vector<fmt_metaentry> meta; + + <b>Is it animated or static ?</b> + bool animated; + +}; + + +enum fmt_compression { + +<b>No compression</b> +CompressionNo = 1, + +<b>RLE compression</b> +CompressionRLE = 2, + +<b>Internal cmpression. E.g. compression_level will be passed to internal routines, +for example in libjpeg, libpng. +Note: if the image can be compressed with RLE encoding and with only RLE +encoding, compression_scheme should be CompressionInternal</b> +CompressionInternal = 4 }; + +<b>Write options for image format</b> +struct fmt_writeoptionsabs +{ + <b>Can be interlaced ?</b> + bool interlaced; + + <b>if interlaced, this value should store preferred number of passes.</b> + s32 passes; + + <b>if the image should be flipped before writing</b> + bool needflip; + + <b> with which compression it can be encoded ? + for example: CompressionNo | CompressionRLE. + it means, that image can be encoded with RLE + method or can be saved without any compression.</b> + s32 compression_scheme; + + <b> minimum compression level, maximum and default. + For example, JPEG library has minimum = 0, + maximum = 100 and default = 25.</b> + s32 compression_min, compression_max, compression_def; + +}PACKED; + +<b>this information will be passed to writing function</b> +struct fmt_writeoptions +{ + <b>write interlaced image or normal ?</b> + bool interlaced; + + <b>with which compression encode the image ?</b> + fmt_compression compression_scheme; + + <b>compression level</b> + s32 compression_level; + + <b>has alpha channel ? If no, A channel in RGBA image will be ignored</b> + bool alpha; + +}PACKED; + + +<b>We can use comparison operators for RGBA and RGB pixels. For example:</b> +<strong> +#define SQ_NEED_OPERATOR_RGBA_RGB + +RGBA rgba; +RGB rgb; +... +if(rgba == rgb) + printf("Pixels are equal!\n"); +</strong> +#if defined SQ_NEED_OPERATOR_RGBA_RGBA +static s32 operator== (const RGBA &rgba1, const RGBA &rgba2) +{ + return (rgba1.r == rgba2.r && rgba1.g == rgba2.g && rgba1.b == rgba2.b && rgba1.a == rgba2.a); +} +#endif + +#if defined SQ_NEED_OPERATOR_RGB_RGBA +static s32 operator== (const RGB &rgb, const RGBA &rgba) +{ + return (rgb.r == rgba.r && rgb.g == rgba.g && rgb.b == rgba.b); +} +#endif + +#if defined SQ_NEED_OPERATOR_RGBA_RGB +static s32 operator== (const RGBA &rgba, const RGB &rgb) +{ + return (rgba.r == rgb.r && rgba.g == rgb.g && rgba.b == rgb.b); +} +#endif + +#endif +</pre> +</body> +</html> diff --git a/doc/html/styles.css b/doc/html/styles.css new file mode 100644 index 0000000..62e1aa3 --- /dev/null +++ b/doc/html/styles.css @@ -0,0 +1,26 @@ +h1, h2, h3 { font-family: tahoma, verdana, Helvetica, arial, sans-serif; } + +a:link.menulink { color: #ffffff; text-decoration: none } +a:visited.menulink { color: #ffffff; text-decoration: none } +a:active.menulink { color: #ffffff; text-decoration: none } +a:hover.menulink { color: #ffffff; text-decoration: underline } + +body.index + { + background: #ffffff; + font-family: Tahoma, Arial, Helvetica, sans-serif; color: #000000; + } + +body { + background: #ffffff; + font-family: Tahoma, Arial, Helvetica, sans-serif; color: #000000; + + background-repeat: no-repeat; + background-attachment: fixed; + background-image: url(belka_bkgr.gif); + background-position: right bottom; + } + +td.menuitem { padding: 3px; } + +p.red { text-indent: 8mm; } |