|
From: Eric B. <er...@go...> - 2001-10-21 22:25:59
|
Andreas Leitner wrote:
>
> Problem fixed. The see code was still looking for EP_EVENT_PARSER,
> whereas it has been renamed to XP_EVENT_PARSER. I have also now
> added code that checks if the class we resolve is actually in the
> system. An exception is raised otherwise. This code is protected
> via an #ifdef and can be enabled by setting ${GOBO_C_DEBUG} before
> executing geant compile in library/xml/impl/expat/spec/c.
I had a chance to have a look at the C code in
library/xml/impl/expat/spec/c when I tried to
make it work with MSVC++ 6.0 this week, and
personally I don't think that it is a good way
of programming to access the Eiffel routines
from C by name using Cecil. It is no safe (see
the exception raisings that you added), it is
error-prone (see the segfault you got just
because you renamed a class), and it is not
efficient (class names and feature names are
probably searched for in hash tables each time
the corresponding Eiffel routine is to be
called, even if the routine won't change between
two calls.
A much better solution is to pass the function
pointers of the Eiffel routines from the Eiffel
side to the C side in an initialization routine,
and then the C code has these functions pointers
in global variables once and for all, and there
is no need for Cecil to get them by name anymore.
Example:
In Eiffel code:
f is
do
...
end
g is
do
...
end
initialize is
-- Pass function pointers of `f' and
-- `g' to C.
do
c_initialize ($f, $g)
end
feature {NONE} -- External
c_initialize (fp, gp: POINTER) is
-- Pass function pointers of `f' and
-- `g' to C.
external
"C"
end
In C code:
EIF_PROCEDURE eif_f, eif_g;
void c_initialize (EIF_PROCEDURE fp, EIF_PROCEDURE gp)
{
eif_f = fp;
eif_g = gp;
}
And now you can replace the code:
void exml_on_element_declaration (void *eiffel_object,
const XML_Char *name,
XML_Content *model)
{
#ifdef ise
EIF_PROCEDURE ep;
EIF_TYPE_ID tid;
tid = eif_type_id ("XP_EVENT_PARSER");
#ifdef GOBO_DEBUG
if (tid == EIF_NO_TYPE)
eif_panic ("Type XP_EVENT_PARSER not in system.");
#endif
ep = eif_procedure ("f", tid);
if (ep == 0)
{ eif_panic ("f not found."); }
else
{ (ep) (eif_access(eiffel_object), (void*) name, (void*) model); }
#endif
}
by:
void exml_on_element_declaration (void *eiffel_object,
const XML_Char *name,
XML_Content *model)
{
#ifdef ise
(eif_f) (eif_access(eiffel_object), (void*) name, (void*) model);
#endif
}
It's safer, more robust, more efficient.
PS: Note that in `exml_on_element_declaration' there is
a extra line in the actual code in the C file:
(ep) (eif_access(eiffel_object), (void*) name, (void*) model);
which should be removed, otherwise the routine is
called twice.
--
Eric Bezault
mailto:er...@go...
http://www.gobosoft.com
|