Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

using windows dll

Status
Not open for further replies.

zby

Programmer
Oct 31, 2003
22
0
0
CZ
I have a separate dll to handle a flatbed scanner written in I don't know what. I also have a list of functions and their description this dll exports (windows help file).

The point is that I'd like to load this dll to my tcl application and use its functions.
How can I do that?

Other questions:
1. Is there a direct or indirect way to use the dll's functions? Do I have to "require" it?
2. Do I have to use some TCL interface to call the dll's functions...
3. Is there a "pure tcl" way to talk to a scanner device?
Can anyone share his/her experience in this issue.

Using ActiveTcl 8.4.6

Thank you very much
 
check out the "load" command:
NAME
load - Load machine code and initialize new commands.

SYNOPSIS
load fileName
load fileName packageName
load fileName packageName interp


DESCRIPTION
This command loads binary code from a file into the application's address space and calls an initialization procedure in the package to incorporate it into an interpreter. fileName is the name of the file containing the code; its exact form varies from system to system but on most systems it is a shared library, such as a .so file under Solaris or a DLL under Windows. packageName is the name of the package, and is used to compute the name of an initialization procedure. interp is the path name of the interpreter into which to load the package (see the interp manual entry for details); if interp is omitted, it defaults to the interpreter in which the load command was invoked.

Once the file has been loaded into the application's address space, one of two initialization procedures will be invoked in the new code. Typically the initialization procedure will add new commands to a Tcl interpreter. The name of the initialization procedure is determined by packageName and whether or not the target interpreter is a safe one. For normal interpreters the name of the initialization procedure will have the form pkg_Init, where pkg is the same as packageName except that the first letter is converted to upper case and all other letters are converted to lower case. For example, if packageName is foo or FOo, the initialization procedure's name will be Foo_Init.

If the target interpreter is a safe interpreter, then the name of the initialization procedure will be pkg_SafeInit instead of pkg_Init. The pkg_SafeInit function should be written carefully, so that it initializes the safe interpreter only with partial functionality provided by the package that is safe for use by untrusted code. For more information on Safe-Tcl, see the safe manual entry.

The initialization procedure must match the following prototype:

typedef int Tcl_PackageInitProc(Tcl_Interp *interp);

The interp argument identifies the interpreter in which the package is to be loaded. The initialization procedure must return TCL_OK or TCL_ERROR to indicate whether or not it completed successfully; in the event of an error it should set the interpreter's result to point to an error message. The result of the load command will be the result returned by the initialization procedure.

The actual loading of a file will only be done once for each fileName in an application. If a given fileName is loaded into multiple interpreters, then the first load will load the code and call the initialization procedure; subsequent loads will call the initialization procedure without loading the code again. It is not possible to unload or reload a package.

The load command also supports packages that are statically linked with the application, if those packages have been registered by calling the Tcl_StaticPackage procedure. If fileName is an empty string, then packageName must be specified.

If packageName is omitted or specified as an empty string, Tcl tries to guess the name of the package. This may be done differently on different platforms. The default guess, which is used on most UNIX platforms, is to take the last element of fileName, strip off the first three characters if they are lib, and use any following alphabetic and underline characters as the module name. For example, the command load libxyz4.2.so uses the module name xyz and the command load bin/last.so {} uses the module name last.

If fileName is an empty string, then packageName must be specified. The load command first searches for a statically loaded package (one that has been registered by calling the Tcl_StaticPackage procedure) by that name; if one is found, it is used. Otherwise, the load command searches for a dynamically loaded package by that name, and uses it if it is found. If several different files have been loaded with different versions of the package, Tcl picks the file that was loaded first.

_________________
Bob Rashkin
rrashkin@csc.com
 
No success. (no Twain_Init procedure found)

The dll hasn't been written for use with tcl. It's just an every dll probaly written in C. Has no TCLish init in it. All I have so far is just that dll plus Twain.h file.

Are there any TCL bindings library to twain.dll (twain_32.dll) or other free scanner handling library out there. I googled, but I haven't been successful so far.

Thank you.
 
Hi zby,

to use this twain_32.dll in TCL you have to create a DLL of your own which provides the interpreter with all the functions you need. You must use the TCL-C-Interface provided with the TCL-API.

I assume that you use some version of Microsoft Visual Studio.

Step 1: Create a Win32 DLL project (from scratch, empty)
Step 2: Write an init function similar to the example below

Code:
/////////////////////////////////////////////////////////////////////////////////////////////////////
extern "C" int Mydll_Init( Tcl_Interp* interp )
/////////////////////////////////////////////////////////////////////////////////////////////////////
{
        // this registers a new command "c_function" with the interpreter.
        // whenever you call "c_function" in TCL actually the C function "test" (see below) will be called
	Tcl_CreateObjCommand( interp, "c_function", 			     test, 0, 0 );

        // You don't neccessarily have to use "provide" if
        // you do not want to "require" this dll.
        // The TCL package system sucks anyway. My opinion.
	//Tcl_PkgProvide(interp, "MyDLL", "1.0");
	return TCL_OK;
}

void test(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj *CONST objv[])
{
        printf( "This is a C function\n" );
}

Step 3: Instead of the example function "test" write your own functions which use (call) the scanner functions you need. e.g. one function per scanner function.

Got it?

When you are done compiling you can then load the dll into the interpreter using
Code:
load mydll.dll Mydll
This will load your own dll and call the function Mydll_Init which will then in turn register all your new commands, PLUS it will implicitely load the twain_32.dll, assuming you have linked your dll with it.

Of course all DLLs must be accessible by the interpreter.

Best thing is to put all DLLs into the same directory as the TCL interpreter, so the load command can find them.

Step 4: Read the Manual about Tcl_CreateObjCommand to find out what the parameters of your functions mean and how to use them (how to handle function parameters specified by your TCL script)

Hope it works for you,
LF28
 
Thank you!

Before rushing headlong into testing it I suppose that the below lines will say a bit about me and my situation.

I have no Visual Studio. Feel a bit ashamed, but what the heck now.
As a matter of fact I am primarily a unix/linux programmer. As far as windows I use ActivePerl and ActiveTcl and so far I din't have to reach beyond the boundaries of packages that those bundles provide.

1. Can I use djgpp instead?
2. If not do I have to stick to Visual Studio?
3. Do I necessarily have to use the same compiler that has been used to compile ActiveTcl?


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top