Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Compiling TCL C++ extension (.so) in cygwin environment

109 views
Skip to first unread message

Michael

unread,
Feb 16, 2006, 1:13:58 PM2/16/06
to
Hi I'm trying to build my C++ extension to run in cygwin tclsh
so I can test stuff on my laptop. This is what I do to build the .so

g++ -c -shared -fPIC filemap.cpp cao.cpp -I.
g++ -shared -fPIC -o libcao.so cao.o filemap.o -ltcl84 -L/lib

This complies with no problems. However when I load in tclsh I get the
following error:

$ tclsh
% load ./libcao.so
couldn't load library "./libcao.so": invalid argument

Any ideas?

Michael

Michael

unread,
Feb 16, 2006, 1:43:02 PM2/16/06
to
BTW, the same compiles and works on SunOS 5.9.

Ralf Fassel

unread,
Feb 16, 2006, 2:43:24 PM2/16/06
to
* "Michael" <chun...@evolving.com>

| g++ -c -shared -fPIC filemap.cpp cao.cpp -I.

Usually -shared only goes in the link stage, not in the compile stage.
Don't know if that hurts here...

| $ tclsh
| % load ./libcao.so
| couldn't load library "./libcao.so": invalid argument

Is this tclsh matching the tcl84 library used to link your .so?
Did you verify that libcao.so indeed contains the object files
(eg list via nm).

R'

Dave Bodenstab

unread,
Feb 16, 2006, 6:13:14 PM2/16/06
to

Cygwin (windoze) requires a .dll extension. Look in the Cygwin
docs; there's an example of how to build a .dll. I've been
compiling TclMagick on Cygwin using (paraphrased):

gcc -mno-cygwin -DUSE_TCL_STUBS -I$(TCL_PREFIX)/include -c file.c
gcc -mno-cygwin -shared -L$(TCL_PREFIX)/lib -o file.dll -ltclstub84

This creates the .dll. I am able to generate the pkgIndex.tcl and
use the package with active state's tcl.

Erik Leunissen

unread,
Feb 16, 2006, 6:15:25 PM2/16/06
to
Michael wrote:
>
> g++ -c -shared -fPIC filemap.cpp cao.cpp -I.
> g++ -shared -fPIC -o libcao.so cao.o filemap.o -ltcl84 -L/lib

The "-L/lib" option will make the linker search in the /lib directory
for any libraries specified on the command line *after* "-L/lib".

Because there is nothing on the command line after "-L/lib", this option
has no effect. You probably did not intend that.

Erik Leunissen
--
leunissen@ nl | Merge the left part of these two lines into one,
e. hccnet. | respecting a character's position in a line.

Michael

unread,
Feb 16, 2006, 9:44:28 PM2/16/06
to
> Cygwin (windoze) requires a .dll extension

Actually single threaded apps built in cygwin environment run faster on
my laptop than on the target sun SPARC IV platform (built with CC). I
see no difference in compiling with -o name.so and -o name.dll

> The "-L/lib" option will make the linker search in the /lib directory
> for any libraries specified on the command line *after* "-L/lib".

I put the -L option there because the linker wouldn't be able to find
the tcl lib.

> Is this tclsh matching the tcl84 library used to link your .so?
> Did you verify that libcao.so indeed contains the object files

Yes, objects are there.

Any other ideas? I need to build with g++ as the extension is written
in C++

Ralf Fassel

unread,
Feb 17, 2006, 4:15:10 AM2/17/06
to
* "Michael" <chun...@evolving.com>

| I need to build with g++ as the extension is written in C++

Wild guess... is your init() routine declared extern "C"? Tcl tries
to run the Cao_Init() function when loading the library, and this has
to be non-C++-name-mangled. But then, if this were the error I would
have expected something along the lines of `could not find init
routine'.

R'

Michael

unread,
Feb 17, 2006, 4:22:37 AM2/17/06
to
Hi, yes. I can get the working on sun so the code should be fine.

I tried with (should make a difference because I'm not worried about
running outside cygwin)

dllwrap --driver-name g++ -o libcao.dll cao.o filemap.o -ltcl84 -lm
-lstdc++

but still get the same error which trying to load.

I guess I need to find out what the error meesage means.

tclsh
load % libcao.dll
couldn't load library "libcao.dll": invalid argument


#include <tcl.h>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <bitset>
#include <time.h>
#include <filemap.h>

extern "C" {
int Cao_Init(Tcl_Interp *interp);
int setVar(
Tcl_Interp *interp, Tcl_Obj * CONST objv[],
std::vector<filemap::fieldinfo>::iterator itr,
std::vector<filemap::fieldinfo>::iterator end);
int Get_Rec( ClientData clientData, Tcl_Interp *interp, int objc,
Tcl_Obj * CONST objv[]);
int Cao_Cmd( ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj
* CONST objv[]);
int Get_Rec( ClientData clientData, Tcl_Interp *interp, int objc,
Tcl_Obj * CONST objv[]);

int Get_Dump ( ClientData clientData, Tcl_Interp *interp, int objc,
Tcl_Obj * CONST objv[]);
int Fin_Cmd( ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj
* CONST objv[]);
}

filemap * fm;

..... function declared

int
Cao_Init(Tcl_Interp *interp)
{

if (Tcl_InitStubs(interp, TCL_VERSION, 0) == 0L) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "cao::parse", Cao_Cmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "cao::dump", Get_Dump, NULL, NULL);
Tcl_CreateObjCommand(interp, "cao::get", Get_Rec, NULL, NULL);
Tcl_CreateObjCommand(interp, "cao::finished", Fin_Cmd, NULL, NULL);
Tcl_PkgProvide(interp, "Cao", "1.0");
return TCL_OK;
}

Ralf Fassel

unread,
Feb 17, 2006, 4:37:06 AM2/17/06
to
* "Michael" <chun...@evolving.com>
| int
| Cao_Init(Tcl_Interp *interp)
| {

Make this the only function in the whole library and put some stderr
output right here to see if you arrive here at all. Leave out
everything, just do a return TCL_OK and see whether this works. Then
line by line add your functionality and see where it breaks.

R'

Christian Gollwitzer

unread,
Feb 17, 2006, 4:41:45 AM2/17/06
to

It works for me, C++ extension wrapped up with SWIG on Cygwin. Are you
sure your tclsh is really cygwin and not windows? I remember that the
supplied "wish" once was/yet is a "normal" windows application without
cygwin, which of course can't load cygwin .so You may try to either
compile your extension with "-mno-cygwin" (but note that this is porting
to windows and may change semantics of some libc functions), or try to
recompile Tcl from sources with "configure" from the unix directory.
In any case, the libtcl you link with must match your tclsh.

Christian

Benjamin Riefenstahl

unread,
Feb 17, 2006, 8:28:45 AM2/17/06
to
Hi Michael,

"Michael" writes:
> int
> Cao_Init(Tcl_Interp *interp)

This should probably be

DLLEXPORT int
Cao_Init(Tcl_Interp *interp)

Windows compilers usually do not export each and every global symbol
of a DLL to outside callers.

benny

Sektor van Skijlen

unread,
Feb 17, 2006, 9:49:10 AM2/17/06
to
Dnia 16 Feb 2006 10:13:58 -0800, Michael skrobie:

Beware that Cygwin currently uses Windows (NOT Cygwin!) version of tclsh84.

I don't know, why. I succeeded to compile tclsh8.5 on my Cygwin in Cygwin
native version and I succeeded. Maybe the problem is with Tk, I didn't try it.

You have to compile your dynamic library as a Windows dll. This is loadable
from tclsh, but I didn't try, how it works.

After some small changes, it is possible to use dll's on a native Tclsh on
Cygwin, but I don't remember how I did it (it was some homecooked version
compiled with unix rules with manually compiled-in windows version for dynamic
libraries).


--
// _ ___ Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl>
\\ L_ |/ `| /^\ ,() <ethourhs(O)wp.pl>
// \_ |\ \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx
"I am allergic to Java because programming in Java reminds me casting spells"

Erik Leunissen

unread,
Feb 17, 2006, 12:04:52 PM2/17/06
to
Michael wrote:

I now remember that I also had this error not so long ago. The cause of
the error was that the call to Tcl_InitStubs() failed. Now that I see in
your code:

> int
> Cao_Init(Tcl_Interp *interp)
> {
>
> if (Tcl_InitStubs(interp, TCL_VERSION, 0) == 0L) {
> return TCL_ERROR;
> }

I'd recommend to check that:
- your invocation is correct (shouldn't it be:

if (Tcl_InitStubs(interp, TCL_VERSION, 0) != TCL_OK) {
^^^^^^^^^

- the linking against the stubs library has been succesful


HTH,

Michael

unread,
Feb 19, 2006, 1:19:49 AM2/19/06
to
Thanks of all your replies. I tried the suggests apart from recompiling
tclsh.

If the tclsh that comes with the latest cygwin is built for windows
then this is probably the problem. When I build my extension I don't
use the -mno-cygwin option. When I do I get lots of errors but the lib
is created. Do I need to include some other lib?

In file included from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:67,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/char_traits.h:46,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/string:47,
from filemap.cpp:1:
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cstdlib:181: error:
`::strtold' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cstdlib:200: error:
`__gnu_cxx::strtold' has not been declared
In file included from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/postypes.h:46,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/iosfwd:50,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:70,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/char_traits.h:46,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/string:47,
from filemap.cpp:1:
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:146: error:
`::fgetwc' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:147: error:
`::fgetws' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:148: error:
`::fputwc' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:149: error:
`::fputws' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:150: error:
`::fwide' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:151: error:
`::fwprintf' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:152: error:
`::fwscanf' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:153: error:
`::getwc' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:154: error:
`::getwchar' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:159: error:
`::putwc' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:160: error:
`::putwchar' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:161: error:
`::swprintf' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:162: error:
`::swscanf' has not been declared
..

/usr/include/tcl.h:391: error: `__int64' does not name a type
/usr/include/tcl.h:392: error: `__int64' does not name a type
/usr/include/tcl.h:640: error: `Tcl_WideInt' does not name a type
/usr/include/tcl.h:776: error: `Tcl_WideInt' does not name a type
/usr/include/tcl.h:1457: error: ISO C++ forbids declaration of
`Tcl_WideInt' with no type
/usr/include/tcl.h:1457: error: typedef `Tcl_WideInt' is initialized
(use __typeof__ instead)
/usr/include/tcl.h:1457: error: `Tcl_DriverWideSeekProc' was not
declared in this scope
/usr/include/tcl.h:1457: error: expected `,' or `;' before '(' token
/usr/include/tcl.h:1545: error: ISO C++ forbids declaration of
`Tcl_DriverWideSeekProc' with no type
/usr/include/tcl.h:1545: error: expected `;' before '*' token
In file included from /usr/include/tcl.h:2250,
from cao.cpp:1:
/usr/include/tclDecls.h:1565: error: expected constructor, destructor,
or type conversion before '*' token
/usr/include/tclDecls.h:1565: error: expected `,' or `;' before '*'
token
/usr/include/tclDecls.h:2119: error: ISO C++ forbids declaration of
`Tcl_DriverWideSeekProc' with no type
/usr/include/tclDecls.h:2119: error: expected `;' before '*' token
In file included from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:67,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/char_traits.h:46,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/string:47,
from cao.cpp:2:
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cstdlib:181: error:
`::strtold' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cstdlib:200: error:
`__gnu_cxx::strtold' has not been declared
In file included from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/postypes.h:46,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/iosfwd:50,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:70,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/char_traits.h:46,
from
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/string:47,
from cao.cpp:2:
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:146: error:
`::fgetwc' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:147: error:
`::fgetws' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:148: error:
`::fputwc' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:149: error:
`::fputws' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:150: error:
`::fwide' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:151: error:
`::fwprintf' has not been declared
/usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:152: error:
`::fwscanf' has not been declared
..

Michael

unread,
Feb 19, 2006, 6:56:06 AM2/19/06
to
After going around and around in circles, I found the answer here. It
is not as straight forward as just using g++.

http://wiki.tcl.tk/2419

Thanks
Michael

Michael

unread,
Feb 19, 2006, 7:45:41 AM2/19/06
to
OK, it didn;t quite work. The run the example and it works. I created a
command in the example file and it work. The all I did was include the
c++ header file for my new class, recomplied and created the dll and
got the same error as before.

couldn't load library "tcldemo.dll": invalid argument

Why does including a header file cause a problem with loading the
library.

Michael

unread,
Feb 19, 2006, 12:22:25 PM2/19/06
to
Finally I got it working but I resorted to building in mingw :( and
linking against the Active State TCL build. So:

Using the example http://wiki.tcl.tk/2419

and the MINGW environment:

http://sourceforge.net/project/showfiles.php?group_id=10894

Michael

Michael

unread,
Feb 20, 2006, 2:22:36 AM2/20/06
to
I tried Swig before but it doesn't support inner classes yet

Michael

Martin

unread,
Feb 23, 2006, 8:05:19 PM2/23/06
to
I got tcl-8.4.12 to compile in native cygwin (unix mode).
'load' works like a charm.
I'll send you the patch if you're interested.

Martin

Sektor van Skijlen

unread,
Feb 24, 2006, 7:14:22 AM2/24/06
to
Dnia 23 Feb 2006 17:05:19 -0800, Martin skrobie:

> I got tcl-8.4.12 to compile in native cygwin (unix mode).
> 'load' works like a charm.
> I'll send you the patch if you're interested.

Please send to someone "responsible".

0 new messages