caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Callback in DLL
@ 2001-12-26 18:42 Warp
  2001-12-28  8:49 ` Xavier Leroy
  0 siblings, 1 reply; 4+ messages in thread
From: Warp @ 2001-12-26 18:42 UTC (permalink / raw)
  To: OCaml

Hello
I got some problems passing a callback function value to a DLL, which will
call the caml function when some event occurs.
In fact, to use the callback_exn C API function, I have to link with the
libcamlrun library, but that's not why I want to do because an interpreter
 ocamlrun ) is already running.

Here's a proposal to resolve such a problem :
a DLL should have an EntryPoint ( called CamlEntryPoint for exemple ) and
when it's first load by the run-time system, it call the DLL EntryPoint
function, passing both cprims and names_of_cprims arrays as parameters. Then
we only have to add a "caml" callback func (useless in caml !) to enable DLL
callback.

I don't know how LabTk works... I'll have a look at it.

Warp

-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Callback in DLL
  2001-12-26 18:42 [Caml-list] Callback in DLL Warp
@ 2001-12-28  8:49 ` Xavier Leroy
  2001-12-28 12:55   ` Warp
  0 siblings, 1 reply; 4+ messages in thread
From: Xavier Leroy @ 2001-12-28  8:49 UTC (permalink / raw)
  To: Warp; +Cc: OCaml

> I got some problems passing a callback function value to a DLL, which will
> call the caml function when some event occurs.
> In fact, to use the callback_exn C API function, I have to link with the
> libcamlrun library, but that's not why I want to do because an interpreter
>  ocamlrun ) is already running.

If you're building a DLL whose purpose is to be loaded inside
ocamlrun, then you should link with ocamlrun.lib, which is an "import
library" around the DLL entry points exported by ocamlrun.

> Here's a proposal to resolve such a problem :
> a DLL should have an EntryPoint ( called CamlEntryPoint for exemple ) and
> when it's first load by the run-time system, it call the DLL EntryPoint
> function, passing both cprims and names_of_cprims arrays as parameters. Then
> we only have to add a "caml" callback func (useless in caml !) to enable DLL
> callback.

There are many more functions (and global variables) from the runtime
system that need to be known to the DLL.  The import library solution
is a lot easier, especially since the source code of the DLL can also
be compiled as a statically-linked library for use with ocamlc -custom.

> I don't know how LabTk works... I'll have a look at it.

Good idea.  You may want to start with a simpler example, e.g.
otherlibs/str/Makefile.nt in the OCaml sources.

On to your other questions:

> I got some trouble with the garbage collector.
> I manage to make callbacks from my dynamic linked library, passing it
> the callbackN_exn C API function address when it loads.
> Now i'm doing theses things :
> [Store a Caml value as a window data]
> So , the user got the ' v ' caml value which mainly contains the real handle
> of the window and the callback.
> And the window itself can obtain ' v ' from handle by calling
> etWindowData( handle_of_window );
> in the window proc I'm getting that ' v ' data like that and then I'm
> calling caml callback.
> All it's fine, but after 10 seconds, the garbage collector collects my ' v '
> data ( I can see that the Tag_val is set to Zero ).

Of course.  You didn't tell it that you've kept a pointer to "v" in
the window data.  So, as far as the GC is concerned, nobody is
pointing to "v", so it can be freed.

> How can i prevent that ?
> Shall I use CAMLparamX and other garbage-living-in-harmony-stuff ?

Yes, you definitely need to learn how to "live in harmony" with the GC :-)

Here, CAMLparamX isn't what you need, because "v" isn't local to the C
function.  You need to use register_global_root().

If you cannot get the memory address where SetWindowData stores its
window data, you'll need to put an additional indirection through a
malloc()-ed block.

> Theses macros are using local_root so do I have to make my library ask the
> current local_root from the interpreter ?

The import library takes care of all that.

- Xavier Leroy
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Callback in DLL
  2001-12-28  8:49 ` Xavier Leroy
@ 2001-12-28 12:55   ` Warp
  2002-01-03 14:34     ` Xavier Leroy
  0 siblings, 1 reply; 4+ messages in thread
From: Warp @ 2001-12-28 12:55 UTC (permalink / raw)
  To: Xavier Leroy; +Cc: OCaml

> > I got some problems passing a callback function value to a DLL, which
will
> > call the caml function when some event occurs.
> > In fact, to use the callback_exn C API function, I have to link with the
> > libcamlrun library, but that's not why I want to do because an
interpreter
> >  ocamlrun ) is already running.
>
> If you're building a DLL whose purpose is to be loaded inside
> ocamlrun, then you should link with ocamlrun.lib, which is an "import
> library" around the DLL entry points exported by ocamlrun.

oups !
I didn't see that one !
Ok, lets try....
1) if I only link ocamlrun.lib, it can't find external "local_roots" needed
in CAMLparamX,
so I have to use my caml_init_func (dll entry point) and a modified
interpreter
which call the entry point passing the adress of local_roots.
2) ... and then, my first call to "alloc" is causing a crash inside
ocamlrun.lib ( perhaps my modified
interpreter is not exporting the function ).

More infos :
- I got a DLL called camlwlib , which is a modified byterun , adding init
calls for dynamic
linked libraries and also a Caml_Run exported function which load a bytecode
file and run it.
- I got a ocamlwrun.exe which only load the camlwlib and call Caml_Run with
the first argument
- I got my DLL called dllwin32ui
- All of theses are build under VC++6

> > Here's a proposal to resolve such a problem :
> > a DLL should have an EntryPoint ( called CamlEntryPoint for exemple )
and
> > when it's first load by the run-time system, it call the DLL EntryPoint
> > function, passing both cprims and names_of_cprims arrays as parameters.
Then
> > we only have to add a "caml" callback func (useless in caml !) to enable
DLL
> > callback.
>
> There are many more functions (and global variables) from the runtime
> system that need to be known to the DLL.  The import library solution
> is a lot easier, especially since the source code of the DLL can also
> be compiled as a statically-linked library for use with ocamlc -custom.

Without local_roots, perhaps I only need to link ocamlrun.lib and
remove my CAMLparam / local / return Macros ?

> > I don't know how LabTk works... I'll have a look at it.
>
> Good idea.  You may want to start with a simpler example, e.g.
> otherlibs/str/Makefile.nt in the OCaml sources.
>
> On to your other questions:
>
> > I got some trouble with the garbage collector.
> > I manage to make callbacks from my dynamic linked library, passing it
> > the callbackN_exn C API function address when it loads.
> > Now i'm doing theses things :
> > [Store a Caml value as a window data]
> > So , the user got the ' v ' caml value which mainly contains the real
handle
> > of the window and the callback.
> > And the window itself can obtain ' v ' from handle by calling
> > etWindowData( handle_of_window );
> > in the window proc I'm getting that ' v ' data like that and then I'm
> > calling caml callback.
> > All it's fine, but after 10 seconds, the garbage collector collects my '
v '
> > data ( I can see that the Tag_val is set to Zero ).
>
> Of course.  You didn't tell it that you've kept a pointer to "v" in
> the window data.  So, as far as the GC is concerned, nobody is
> pointing to "v", so it can be freed.

Actually , "v" is returned to the caml, and then let-stored. So it is
referenced.

> > How can i prevent that ?
> > Shall I use CAMLparamX and other garbage-living-in-harmony-stuff ?
>
> Yes, you definitely need to learn how to "live in harmony" with the GC :-)
>
> Here, CAMLparamX isn't what you need, because "v" isn't local to the C
> function.  You need to use register_global_root().
>
> If you cannot get the memory address where SetWindowData stores its
> window data, you'll need to put an additional indirection through a
> malloc()-ed block.

I'll try this....

> > Theses macros are using local_root so do I have to make my library ask
the
> > current local_root from the interpreter ?
>
> The import library takes care of all that.

"unresolved external symbol _local_roots"

----

Thanks a lot, I'll try at least to *bug* in harmony with the GC :)

Warp

-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Callback in DLL
  2001-12-28 12:55   ` Warp
@ 2002-01-03 14:34     ` Xavier Leroy
  0 siblings, 0 replies; 4+ messages in thread
From: Xavier Leroy @ 2002-01-03 14:34 UTC (permalink / raw)
  To: Warp; +Cc: OCaml

> > If you're building a DLL whose purpose is to be loaded inside
> > ocamlrun, then you should link with ocamlrun.lib, which is an "import
> > library" around the DLL entry points exported by ocamlrun.
> 
> 1) if I only link ocamlrun.lib, it can't find external "local_roots" needed
> in CAMLparamX

You probably forgot to compile your C code with the /MD flag (meaning
"multithreaded DLL").

Explanation: the Win32 dynamic linker cannot cope with shared global
variables, so these need to be accessed by calls to shared functions.
The C compiler generates the calls provided the global variable is
declared "dllimport".  The Caml header files add the proper
declaration provided the _DLL symbol is defined.  The C compiler
defines _DLL if it is invoked with the /MD flag.  End of inference :-)

> so I have to use my caml_init_func (dll entry point) and a modified
> interpreter
> which call the entry point passing the adress of local_roots.

No you don't have to modify anything.  Just read carefully the
makefiles in the system sources and follow what's done there.

> > Of course.  You didn't tell it that you've kept a pointer to "v" in
> > the window data.  So, as far as the GC is concerned, nobody is
> > pointing to "v", so it can be freed.
> 
> Actually , "v" is returned to the caml, and then let-stored. So it is
> referenced.

All right, but the GC also moves live blocks around, so it really
needs to know all the pointers to the block.

- Xavier Leroy
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-01-03 14:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-12-26 18:42 [Caml-list] Callback in DLL Warp
2001-12-28  8:49 ` Xavier Leroy
2001-12-28 12:55   ` Warp
2002-01-03 14:34     ` Xavier Leroy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).