Re: [ooc-compiler] DLL creation with oo2c?
Brought to you by:
mva
|
From: Stewart G. <sgr...@ii...> - 2004-07-21 09:08:05
|
On Wednesday, July 21, 2004, at 08:55 AM, Frank Hrebabetzky wrote:
>> The information to which shared library a module belongs to is
>> available in some places, although it is not passed on into the
>> generated C code until now. The current code base writes information
>> on library membership into the modules' symbol file. Adding it to the
>> header files as well should be easy, since the .oh and .Sym carry
>> pretty much the same information, only in different formats.
>> Don't know if this is sufficient, though, since it only covers the
>> identity of the used code. It looks to me like the identity of the
>> using code plays into this dllimport/export issue as well.
>> -- mva
>
> I don't fully understand this, but my reasoning is the following:
>
> - A DLL is a piece of executable code.
> - Once code is compiled, the source language doesn't matter any more.
> - So if DLLs can be generated from C source, this should be possible
> for Oberon too.
Correct. But the source language does matter up to a point:
- The procedures need to use the same calling convention. Normally,
this will be pascal (stdcall) or C (cdecl). Both are supported by OOC
at present, as is fastcall and vtable method dispatch. There are
additional conventions used by C++ compilers which are not supported
(eg. thiscall).
- Any data structures need to use compatible layouts. Using OOC, you
can control alignment in records so this is not likely to be a problem.
OOC also supports some interoperability between C and Oberon-2 strings
(ie. via CSTRING).
- To link correctly, the languages need to use compatible names for
procedures and variables. OOC decorates function names by appending the
module name. For example, procedure "P" in module "M" is called "P__M"
in the object file. I believe that you can override this naming by
supplying your own name. Of course, you are then responsible for
ensuring that you don't generate name clashes between module. A similar
issue exists with C++ since it decorates procedure names with type
information (ie. to support name overloading).
- Another option to handle language-independent linking is via COM.
This is also possible using OOC, since you can access and implement COM
objects via VTABLE records.
> So why would you need to know which shared library a module belongs to?
The linker needs to know which symbols are to be imported and exported
by the DLL or EXE. There are two ways of specifying this: via a
hand-built ".DEF" file, or by tagging declarations in the source code
(ie: __declspec(dllexport) to export a function, __declspec(dllimport)
to import a function).
If you are prepared to build your own ".DEF" file, then there is no
problem. You could probably even do this with existing object files
generated by the mingw32 compiler and the appropriate link commands.
This might work if you have just a few functions to declare.
To use the tagging approach, the C compiler needs to know explicitly
which functions are imported and exported between DLLs. One way to do
it is like this:
IF module "A" is part of a library, THEN every exported object
(variable, procedure, type descriptor) is declared DECL_A in the
oo2c-generated header files.
At compile-time (ie. by gcc), the meaning of DECL_A changes.
IF compiling the implementation of module "A" THEN
DECL_A is "__declspec(dllexport)"
ELSE (* compiling a module "B" that imports "A" *)
IF "A" and "B" are modules in the same library THEN
DECL_A is ""
ELSE
DECL_A is "__declspec(dllimport)"
END
END
This can probably be done with a little trickery using the
pre-processor, but to make it work OOC needs tag the generated ".oh"
files so that the C compiler knows whether an imported module is in the
same or a different DLL. However, this is a general solution which
should allow you to mix and match modules across DLL boundaries.
One final issue is initialisation. Normally, OOC calls the module
initialisation statements from the main() function. For a DLL, this
should logically be done from the DLL entry point. I'm not sure how
this is currently handled. I believe that OOC currently only links
libraries at load-time, not at run-time. In this case, the
initialisation might still all be done from main(). If your DLL is to
be loaded at run-time, or into a foreign language environment, it would
need to do the initialisation in DllMain().
Here are some relevant references:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
vccore98/html/_core_dll_tasks.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
vccore98/html/_core_export_from_a_dll.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
dllproc/base/dynamic_link_library_entry_point_function.asp
Cheers,
Stewart
|