From: Exchange CAPITALS for correct address on
On Sat, 30 Jan 2010 03:00:48 -0800 (PST), Alexandre Ferrieux
<alexandre.ferrieux(a)gmail.com> wrote:

>While 100% seconding Jan's wise words...
please see my reply to Jan :-)

> let me just mention "ffidl" for
>the case where you really have your dynamic library in both
>environments (a .dll and a .so):

Thanks for Your hint. Unfortunately ffidl is just one of these things,
i find unuseable at the moment, because they are too complicated
for me. Maybe within one or two years i can manage this, but i need
to do the first step before the second, i.e. i need to learn, how to
access a DLL the simple way, then i can upgrade to ffidl.

By the way, there was a discussion about ffidl and possible
errors in it on comp.lang.forth some time ago, because Gforth also
uses ffidl as foreign library interface. So for sure i will avoid it,
until i know, that i can master it. I do not want to look for
other peoples errors, i want to do my own errors :-))

>The price to pay is getting the arguments' types right of course.
For a C and assembler programmer this is no surprise.

Thanks again
Klaus
From: Alexandre Ferrieux on
On Feb 1, 10:56 am, Exchange CAPITALS for correct address
<Slaus.Keegeba...(a)gmx.de> wrote:
>
>
> > let me just mention "ffidl" for
> >the case where you really have your dynamic library in both
> >environments (a .dll and a .so):
>
> Thanks for Your hint. Unfortunately ffidl is just one of these things,
> i find unuseable at the moment, because they are too complicated
> for me. Maybe within one or two  years i can manage this, but i need
> to do the first step before the second, i.e. i need to learn, how to
> access a DLL the simple way, then i can upgrade to ffidl.

Sorry, I don't get it. In a nearby post you say that you don't want to
"spoil" your beautifully generic code with Tcl-specific glue. I
understand this argument perfectly. Then you say that you are used to
calling it from other scripting languages directly. Hence, these
languages have a generic dlopen() gateway. Very good.
Then I give you the name of the generic dlopen() gateway for Tcl,
which is ffidl. And you say it is too complicated ?

This I don't understand: sheer logic indicates that in _any_ language,
calling a foreign dynamic library implies wrapping one's head around
the types in the prototype, and bridging whatever gap exists between
the C types and the host language's ones.
That is exactly what the main call in the ffidl API does:

::ffidl::callout name {?arg_type1 ...?} return_type $address

(where $address is obtained through ::ffidl::symbol).

Now please explain: what, in these other scripting languages, makes
calling arbitrary functions enromously simpler than the above line ?

> By the way, there was a discussion about ffidl and possible
> errors in it on comp.lang.forth some time ago, because Gforth also
> uses ffidl as foreign library interface. So for sure i will avoid it,
> until i know, that i can master it. I do not want to look for
> other peoples errors, i want to do my own errors :-))

Beware of hasty decisions. Ffidl is really a Tcl-specific wrapper
above libffi, which is the real worker for cross-platform dynamic
calling.
What you have in Gforth is a similar wrapper specific to Forth, which
may have its own personal bugs. Unimpressed ;-)

> For a C and assembler programmer this is no surprise.

Then maybe you can also comment on the suggestion of SWIG which was
made in this thread.
Of course this means building a (eeeeek!) Tcl-specific wrapper, though
automatically.
You then will have to decide between

(a) mastering the straightforward syntax of ffidl and directly
calling your pristine dll/so

(b) using the automated SWIG tool and building a Tcl wrapper, which
you'll then [load].

-Alex
From: nedbrek on
Hello,

"Exchange CAPITALS for correct address" <Slaus.Keegebarth(a)gmx.de> wrote in
message news:jg6dm5hgthuhcoar84br6j6u2kbd6tusnt(a)4ax.com...
> On Fri, 29 Jan 2010 18:44:02 -0500, "nedbrek" <nedbrek(a)yahoo.com>
> wrote:
>>...
>>Tcl is very flexible, there are a number of different ways to go about
>>things, depending on what you are looking for.
>
> I just want to start with the simplest way available :-)
>

Understandable :)

>>Is the DLL built from code you have? If so, you can include the Tcl
>>adapter
>>code in it. If it is called mydll.dll, then create a function:
>>extern "C" // for C++ or Pascal/Delphi
>>int Mydll_Init(Tcl_Interp *interp); // may need declspec(dllexport)
>
> The most important DLL is made from my own code. If it is necessary, i
> can reach each and every foreign DLL from here, because it is written
> in C and i can extend it. But introducing new names in this DLL
> requires to relink all my C-programs, because they use static loading
> at start time. And i really do not like to put Tcl-specific code into
> a library for general use (it is used by C-, Forth, Delphi- and
> AutoHotKey-programs). If it is unavoidable, i can live with it, but i
> count it as a big minus for Tcl. I loose overview, if things are
> spread across too much places.

Ok, if you are loading DLL's from a DLL, then you should be able to create a
new DLL which will be loaded by Tcl. Then it can load all the others, as
needed.

>>In Tcl:
>>% load mydll.dll
>
> Are You sure, that this is really called "load" ? A search for "load"
> in Tcls wiki turns up a lot of different items.

Yes, make sure to check the man pages or .hlp file first. I downloaed the
HTML version of the man pages, and keep a bookmark in Firefox. I often have
a whole window filled up with tabs (one for Tcl, one for Tk, one for the C
API, and some wiki tabs).

"load - Load machine code and initialize new commands"

The alternative is to use a package (package require), but that is more
complicated...

>>Then that init function is called. Whatever else you do, make sure to
>>create a new command ("mycmd"), and attach whatever state you need with
>>it.
>
> What does "state" mean ?

I have a Tcl program that interfaces to some C++ code. Here is my init
function (for nstclgui.so):

extern "C"
int Nstclgui_Init(Tcl_Interp *interp)
{
initNameArrays(); // initialize global variables

NewStarsTcl *nstp = new NewStarsTcl; // class to interface to C++
nstp->setEnums(interp); // class method to populate some Tcl variables
using Tcl_SetVar

// create the Tcl command
Tcl_CreateObjCommand(interp, "newStars", generate, nstp, destructor);

return TCL_OK;
}

The NewStarsTcl object "nstp" is my "state". It is passed to every command
callback (the fourth argument in create command). It stores everything I
need to remember in between calls from Tcl (mostly file handles, and some
cached info extracted from the C++ data structures).

"generate" is my command handler, and "destructor" is called when Tcl
unloads the dll.

>>Then in Tcl:
>>% mycmd args
>>Will transfer back to your code.
>
> Isn't it possible to make the initialization code inside Tcl? Why do i
> need to do it inside the DLL?

You can do whatever you like in Tcl or the _Init function. "mycmd" will
call your version of "generate". So it is responsive to user input (say a
script attached to a dialog).

> Thank You, Ned. At least i am one step ahead, although i still do have
> a lot more questions than answers. At the moment mastering Tcl seems
> to consume more time than i can ever gain by using Tcl.
> But in a Tcl newsgroup i probably should not ask for better
> alternatives ;-))

It takes a while to get used to doing things "the Tcl way" :) Once you do,
you'll find you are a lot more productive.

Ned


From: Exchange CAPITALS for correct address on
On Mon, 1 Feb 2010 08:14:19 -0500, "nedbrek" <nedbrek(a)yahoo.com>
wrote:

snip....snip
>"load - Load machine code and initialize new commands"
>
>The alternative is to use a package (package require), but that is more
>complicated...

I do not have the smallest idea, how to use a package.
I tried load and it produced a real error message: it wants to have
Mydll_init(). I wrote Mydll_Init() { sleep( 2 seconds); return(0).}
and a tcl window popped up after 2 seconds. First problem solved.


>>>Then that init function is called. Whatever else you do, make sure to
>>>create a new command ("mycmd"), and attach whatever state you need with
>>>it.

I read about this function (i also saw,that i should include tcl.h),
but once again i do not have the smallest idea, where to get it.


>> What does "state" mean ?
>I have a Tcl program that interfaces to some C++ code. Here is my init..

Aaah, i see. My routines are all stateless, so i just enter 0.


>It takes a while to get used to doing things "the Tcl way" :) Once you do,
>you'll find you are a lot more productive.

This was the reason, why i have choosen it. In the moment, it is just
the opposite. I hope i find the solution before i loose patience :-)
I now have already spent more time to access a DLL than i have needed
to learn to write one!

Thanks again for Your help
Klaus
From: Roger O on

Surely running SWIG on the header files of the DLL to access is not so
very hard. SWIG does all the grunt work. You then call the functions
in the DLL with the same names and Tcl-ized arguments as in the C/C++
code that is presumably also using this DLL. SWIG even goes one step
further and makes an interface to the data structures defined in the
header files, not just the functions.

In the simplest case, it is one command that makes a bit of C code you
compile. Then, load your untouched DLL, and then load this wrapper.
Then get to work.

I think the discussion here was more work/time than generating a Tcl
interface from SWIG...

--
Roger Oberholtzer