Browse files

generate.io, OpenGL, Box, Image, Regex and Range on Windows/MinGW.

1. MINGW DLL EXPORT/IMPORT

a) When functions in a DLL are not declared/defined as dllexport, all the functions are automatically exported by gcc (dll.a)

b) Functions auto-exported by gcc are exported using thunks in the dll.a file (function pointers from C.dll will differ in two different A and B dlls both loading C. dll)

c) When AT LEAST one function in the dll is declared/defined as dllexport, ONLY that/those function/s will be exported

d) Functions exported with dllexport won't use a thunk in the dll.a file (function pointers from C.dll will be the same in two different A and B dlls both loading C. dll).

2. THE PROBLEM

a) generate.io is not defining the Init function as dllexport for MinGW
b) Box and Image addons are exporting some functions (ie: for the OpenGL addon to use them). Those addons are using dllexport/dllimport.
c) So, loading Box and Image addons will fail ("Init function not found") due to 2.a + 2.b = 1.c

To fix this situation (try 1):
d) If we remove the dllexport/dllimport modifiers in Box and Image addons, all the functions will be exported, including their Init function (see 2.a and 1.a)
e) Box and Image addons won't fail to load.
f) But OpenGL addon will fail to load ("missing protos") due to 2.d and then 1.b.

To fix this situation (try 2 OK):
g) Don't remove the dllexport/dllimport modifiers from Box and Image addons
h) Apply dllexport to the Init function in generate.io, so we will have 1.c and 1.d in ALL the addons.
i) Now, addons won't fail to find their Init function (1.c) and won't have 2.f anymore (1.d)
j) But now, due to 1.c, building Regex addon will fail because it depends on Range addon wich is not explicitly exporting functions.
k) We have to create an IoRangeApi.h (ala Box e Image), then apply the IORANGE_API modifier to the functions being imported by Regex at least, and add a BUILDING_RANGE_ADDON definition to the Range CMakeLists.txt file.

Now, OpenGL, Box, Image, Regex and Range will build and load correctly.
  • Loading branch information...
1 parent 288ed40 commit 1ffd508f584119710c83f883239665659d4b7544 @omf omf committed Mar 23, 2011
View
2 addons/Range/CMakeLists.txt
@@ -20,6 +20,8 @@ set(SRCS
"${CMAKE_CURRENT_SOURCE_DIR}/source/IoRangeInit.c"
)
+add_definitions(-DBUILDING_RANGE_ADDON)
+
# Now build the shared library
add_library(IoRange SHARED ${SRCS})
add_dependencies(IoRange iovmall)
View
4 addons/Range/source/IoRange.c
@@ -68,7 +68,7 @@ IoRange *IoRange_rawClone(IoRange *proto)
return self;
}
-IoRange *IoRange_new(void *state)
+IORANGE_API IoRange *IoRange_new(void *state)
{
IoRange *proto = IoState_protoWithInitFunction_(state, IoRange_proto);
return IOCLONE(proto);
@@ -228,7 +228,7 @@ IoObject *IoRange_value(IoRange *self, IoObject *locals, IoMessage *m)
/* ----------------------------------------------------------- */
-IoRange *IoRange_setRange(IoRange *self, IoObject *locals, IoMessage *m)
+IORANGE_API IoRange *IoRange_setRange(IoRange *self, IoObject *locals, IoMessage *m)
{
/*doc Range setRange(start, end, increment)
Has several modes of operation. First, if only two parameters are specified,
View
5 addons/Range/source/IoRange.h
@@ -8,6 +8,7 @@
#include "Common.h"
#include "IoObject.h"
+#include "IoRangeApi.h"
#ifdef __cplusplus
extern "C" {
@@ -29,7 +30,7 @@ typedef struct
IoRange *IoRange_rawClone(IoRange *self);
IoRange *IoRange_proto(void *state);
-IoRange *IoRange_new(void *state);
+IORANGE_API IoRange *IoRange_new(void *state);
void IoRange_free(IoRange *self);
void IoRange_mark(IoRange *self);
@@ -43,7 +44,7 @@ IoObject *IoRange_previous(IoRange *self, IoObject *locals, IoMessage *m);
IoObject *IoRange_index(IoRange *self, IoObject *locals, IoMessage *m);
IoObject *IoRange_value(IoRange *self, IoObject *locals, IoMessage *m);
-IoRange *IoRange_setRange(IoRange *self, IoObject *locals, IoMessage *m);
+IORANGE_API IoRange *IoRange_setRange(IoRange *self, IoObject *locals, IoMessage *m);
IoRange *IoRange_rewind(IoRange *self, IoObject *locals, IoMessage *m);
IoObject *IoRange_foreach(IoRange *self, IoObject *locals, IoMessage *m);
IoObject *IoRange_select(IoRange *self, IoObject *locals, IoMessage *m);
View
15 addons/Range/source/IoRangeApi.h
@@ -0,0 +1,15 @@
+#ifndef IO_RANGE_H_
+#define IO_RANGE_H_
+
+#if defined(WIN32)
+#if defined(BUILDING_RANGE_ADDON)
+#define IORANGE_API __declspec(dllexport)
+#else
+#define IORANGE_API __declspec(dllimport)
+#endif
+
+#else
+#define IORANGE_API
+#endif
+
+#endif
View
5 addons/generate.io
@@ -6,6 +6,7 @@
Addon := Object clone do(
platform := System platform split at(0) asLowercase
+ onWindows := platform == "windows" or platform == "mingw"
isStatic := false
with := method(dir,
@@ -24,7 +25,7 @@ Addon := Object clone do(
initFileName := inlineMethod("source/Io#{directory name}Init.c" interpolate)
generateInit := method(
- if(platform != "windows" and directory directoryNamed("source") filesWithExtension("m") size != 0, return)
+ if(onWindows not and directory directoryNamed("source") filesWithExtension("m") size != 0, return)
initFile := directory fileNamed(initFileName) remove create open
initFile write("#include \"IoState.h\"\n")
initFile write("#include \"IoObject.h\"\n\n")
@@ -60,7 +61,7 @@ Addon := Object clone do(
initFile write("void " .. f name fileName .. "Init(void *context);\n")
)
- if (platform == "windows",
+ if (onWindows,
initFile write("__declspec(dllexport)\n")
)
initFile write("\nvoid Io" .. directory name .. "Init(IoObject *context)\n")

0 comments on commit 1ffd508

Please sign in to comment.