Quantcast

using an external variable in C++ in a shared library

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

using an external variable in C++ in a shared library

Neil DSouza
I am trying to create a shared library on Windows. I am able to create this
shared library on linux but on windows I get linker errors. I am using the MinGW
G++ 4.5 compiler. I will first present the source code to the example on linux ,
and then present the file which I tried to change on windows.

/home/nxd/Progs/C++/shared-lib>cat lib_interface.h

#ifndef LIBINTERFACE_H
#define LIBINTERFACE_H

int func(int a);

#endif /* LIBINTERFACE_H */
/home/nxd/Progs/C++/shared-lib>cat sh_lib.cpp
extern int b;

int func(int a)
{
 return a+b;
}
/home/nxd/Progs/C++/shared-lib>cat main.cpp
#include <iostream>
#include "lib_interface.h"

int b;

int main()
{
 b=10;
 std::cout << func(20) << std::endl;
}

/home/nxd/Progs/C++/shared-lib>cat Makefile
OBJS = main.o sh_lib.o

test: main.o libshared.so
 g++ -L. -o$@ main.o -lshared

main.o: main.cpp lib_interface.h
 g++ -c -Wall -fPIC $<

sh_lib.o: sh_lib.cpp lib_interface.h
 g++ -c -Wall -fPIC $<

libshared.so: sh_lib.o
 ld -shared -soname=libshared.so -o libshared.so.1 $<
 ln -s libshared.so.1 libshared.so

.PHONY: clean

clean:
 rm *.o *.so *.so.1
/home/nxd/Progs/C++/shared-lib>make
g++ -c -Wall -fPIC main.cpp
g++ -c -Wall -fPIC sh_lib.cpp
ld -shared -soname=libshared.so -o libshared.so.1 sh_lib.o
ln -s libshared.so.1 libshared.so
g++ -L. -otest main.o -lshared
/home/nxd/Progs/C++/shared-lib>LD_LIBRARY_PATH=. ./test
30

I tried to make a shared library out of sh_lib.cpp using MinGW g++ on Windows.
The reason there are so many comments is because of the many things I tried
before I decided to post this.

/home/nxd>cat sh_lib.cpp
//extern "C" __declspec(dllimport) int b;
//#ifdef __cplusplus
//extern "C" {
//#endif

__declspec(dllimport) extern int b;
//__declspec(dllimport) int b;
//extern int b;

//#ifdef __cplusplus
//}
//#endif

int func(int a)
{
 return a+b;
}

Here is the relevant portion of the Makefile with various tweaks. The options
passed to the linker that you see below were added one by one to try to get rid
of the link error. The ld command below was just to be sure that the linker was
indeed getting the options. The preceding hyphen tells make to run the next
command even if the current one had errors.

sh_lib.o: sh_lib.cpp lib_interface.h
 g++ -c -Wall -fPIC $<

libshared.so: sh_lib.o
 -ld -shared --enable-auto-import --unresolved-symbols=ignore-in-shared-libs \
   -soname=libshared.so --allow-shlib-undefined -o libshared.so.1 $<
 g++ -shared  -Wl,--unresolved-symbols=ignore-in-shared-libs \
   -Wl,--enable-auto-import -Wl,--allow-shlib-undefined  \
   -Wl,-soname,libshared.so -o libshared.so.1 $<

My Question: how can I compile sh_lib.cpp into a dll using the extern variable
like the way it works in linux?. I did read the stackoverflow article :
http://stackoverflow.com/questions/56500/cant-access-variable-in-c-dll-from-a-c-app
, but "I think" there is a subtle difference here between the 2 cases. There he
was trying to link with a file, here I am trying to create a shared library,
using a variable for which storage has not been allocated (extern), and I want
to tell the linker to ignore this variable's storage when creating the library -
it will be resolved when I am linking with an exe. I am currently managing this
problem with static linking.

Many thanks for your help in advance.



------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using an external variable in C++ in a shared library

JonY-3
On 9/11/2010 16:40, Neil DSouza wrote:

> I am trying to create a shared library on Windows. I am able to create this
> shared library on linux but on windows I get linker errors. I am using the MinGW
> G++ 4.5 compiler. I will first present the source code to the example on linux ,
> and then present the file which I tried to change on windows.
>
> /home/nxd/Progs/C++/shared-lib>cat lib_interface.h
>
> #ifndef LIBINTERFACE_H
> #define LIBINTERFACE_H
>
> int func(int a);
>
> #endif /* LIBINTERFACE_H */
> /home/nxd/Progs/C++/shared-lib>cat sh_lib.cpp
> extern int b;
>
> int func(int a)
> {
>   return a+b;
> }
> /home/nxd/Progs/C++/shared-lib>cat main.cpp
> #include<iostream>
> #include "lib_interface.h"
>
> int b;
>
> int main()
> {
>   b=10;
>   std::cout<<  func(20)<<  std::endl;
> }
>
> /home/nxd/Progs/C++/shared-lib>cat Makefile
> OBJS = main.o sh_lib.o
>
> test: main.o libshared.so
>   g++ -L. -o$@ main.o -lshared
>
> main.o: main.cpp lib_interface.h
>   g++ -c -Wall -fPIC $<
>
> sh_lib.o: sh_lib.cpp lib_interface.h
>   g++ -c -Wall -fPIC $<
>
> libshared.so: sh_lib.o
>   ld -shared -soname=libshared.so -o libshared.so.1 $<
>   ln -s libshared.so.1 libshared.so
>
> .PHONY: clean
>
> clean:
>   rm *.o *.so *.so.1
> /home/nxd/Progs/C++/shared-lib>make
> g++ -c -Wall -fPIC main.cpp
> g++ -c -Wall -fPIC sh_lib.cpp
> ld -shared -soname=libshared.so -o libshared.so.1 sh_lib.o
> ln -s libshared.so.1 libshared.so
> g++ -L. -otest main.o -lshared
> /home/nxd/Progs/C++/shared-lib>LD_LIBRARY_PATH=. ./test
> 30
>
> I tried to make a shared library out of sh_lib.cpp using MinGW g++ on Windows.
> The reason there are so many comments is because of the many things I tried
> before I decided to post this.
>
> /home/nxd>cat sh_lib.cpp
> //extern "C" __declspec(dllimport) int b;
> //#ifdef __cplusplus
> //extern "C" {
> //#endif
>
> __declspec(dllimport) extern int b;
> //__declspec(dllimport) int b;
> //extern int b;
>
> //#ifdef __cplusplus
> //}
> //#endif
>
> int func(int a)
> {
>   return a+b;
> }
>
> Here is the relevant portion of the Makefile with various tweaks. The options
> passed to the linker that you see below were added one by one to try to get rid
> of the link error. The ld command below was just to be sure that the linker was
> indeed getting the options. The preceding hyphen tells make to run the next
> command even if the current one had errors.
>
> sh_lib.o: sh_lib.cpp lib_interface.h
>   g++ -c -Wall -fPIC $<
>
> libshared.so: sh_lib.o
>   -ld -shared --enable-auto-import --unresolved-symbols=ignore-in-shared-libs \
>     -soname=libshared.so --allow-shlib-undefined -o libshared.so.1 $<
>   g++ -shared  -Wl,--unresolved-symbols=ignore-in-shared-libs \
>     -Wl,--enable-auto-import -Wl,--allow-shlib-undefined  \
>     -Wl,-soname,libshared.so -o libshared.so.1 $<
>
> My Question: how can I compile sh_lib.cpp into a dll using the extern variable
> like the way it works in linux?. I did read the stackoverflow article :
> http://stackoverflow.com/questions/56500/cant-access-variable-in-c-dll-from-a-c-app
> , but "I think" there is a subtle difference here between the 2 cases. There he
> was trying to link with a file, here I am trying to create a shared library,
> using a variable for which storage has not been allocated (extern), and I want
> to tell the linker to ignore this variable's storage when creating the library -
> it will be resolved when I am linking with an exe. I am currently managing this
> problem with static linking.
>
> Many thanks for your help in advance.
>
>

Hi,

first of all, stop trying to be smart by using ld directly. Next, remove
-fPIC and --allow-shlib-undefined, it does not work for windows, Windows
needs all symbols resolved, your extern variable cannot work at all.

To build a shared dll, just use "g++ -shared -o <your dll name> <your
objects>".

------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using an external variable in C++ in a shared library

Neil DSouza
JonY <jon_y@...> writes:

> Hi,
>
> first of all, stop trying to be smart by using ld directly.
Honestly I wasn't. The makefile started to look like that after many iterations
between linux and windows in trying to get the example to work.

> Next, remove
> -fPIC and --allow-shlib-undefined, it does not work for windows, Windows
> needs all symbols resolved, your extern variable cannot work at all.

Thanks - this is exactly what I needed. So I will stick with static linking.

Kind Regards,
Neil

> To build a shared dll, just use "g++ -shared -o <your dll name> <your
> objects>".
>




------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using an external variable in C++ in a shared library

Tor Lillqvist
In reply to this post by Neil DSouza
Your problem is that you want to use a variable defined in the main
executable in a shared library. This is more complex to get right on
Windows that on ELF-based systems like Linux.

It is not exactly hard, but the straightforward way to do it causes
considerable inflexibility in the shared library: it works only when
the main executable has exactly the file name specified when building
the "import library" for the main executable. (Yes, the main
executable is treated as if it, too was kind of a library when doing
this.)

That might not be a problem for you if the shared library in question
is to be used only by a single executable that always will have the
same name. (Just the basename, whatever.exe, needs to be fixed, not
the pathname.)

But in general, I would advice to redesign the API of the software you
are building to avoid having to use variables defined in the main
executable in a shared library. A common method is to have the
variable in question as static (not visible to the outside) in the
main program, but pass its addresses to the functions in a shared
library that need it. (For instance, in more complex cases, to some
initialization function for the shared library.) (Typically one
doesn't do this for each separate variable needed to be handled like
this, but collects them into some structure, of course, and passes the
address of that struct to the shared library.)

It's not just variables that need to be handled specially if defined
in the main executable and used in a shared library. It's the same for
functions, too. Also for them the recommended way is to collect
pointers to such functions into a struct and pass that to a shared
library that needs to call them.

(Note also that in general, using variables, as opposed to just
functions, in the API of a shared library also causes some extra pain
on Windows, so that is best avoided, too.)

Anyway, to get the thing working as you want, below are modifications
of your sample source files and a Makefile (just for MinGW in this
case). Obviously your actual code will need ifdefs around the
Windows-specific stuff (the __declspec decorations).

Cheers,
--tml

--- lib_interface.h:

#ifndef LIBINTERFACE_H
#define LIBINTERFACE_H

int func(int a);

#endif /* LIBINTERFACE_H */

--- sh_lib.cpp:

extern __declspec(dllimport)  int b;

int func(int a)
{
 return a+b;
}

--- main.cpp:

#include <iostream>
#include "lib_interface.h"

__declspec(dllexport) int b;

int main()
{
 b=10;
 std::cout << func(20) << std::endl;
}

--- main.def:

EXPORTS
b DATA

--- Makefile:

all : main.exe sh_lib.dll

sh_lib.dll libsh_lib.dll.a : libmain.dll.a
        g++ -Wall -shared -o sh_lib.dll sh_lib.cpp libmain.dll.a
-Wl,-out-implib,libsh_lib.dll.a

libmain.dll.a : main.def
        dlltool --input-def main.def --output-lib libmain.dll.a --dllname main.exe

main.exe : libsh_lib.dll.a
        g++ -Wall -o main.exe main.cpp libsh_lib.dll.a

clean :
        rm -f *.exe *.dll *.a *.o

------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using an external variable in C++ in a shared library

Neil DSouza
Tor Lillqvist <tml@...> writes:

> Anyway, to get the thing working as you want, below are modifications
> of your sample source files and a Makefile (just for MinGW in this
> case). Obviously your actual code will need ifdefs around the
> Windows-specific stuff (the __declspec decorations).

First of all - thank you for this.

> It is not exactly hard, but the straightforward way to do it causes
> considerable inflexibility in the shared library: it works only when
> the main executable has exactly the file name specified when building
> the "import library" for the main executable. (Yes, the main
> executable is treated as if it, too was kind of a library when doing
> this.)
>
> That might not be a problem for you if the shared library in question
> is to be used only by a single executable that always will have the
> same name. (Just the basename, whatever.exe, needs to be fixed, not
> the pathname.)

And thank you for pointing this out. The straightforward solution for my project
will not work because the executable needs to be different as I will explain my
application in the next paragraph - so  I would have to re-run dll tool every
time and re-create the shared lib after that with the new exe name, which
defeats the purpose of the shared library in the first place.

> But in general, I would advice to redesign the API of the software you
> are building to avoid having to use variables defined in the main
> executable in a shared library. A common method is to have the
> variable in question as static (not visible to the outside) in the
> main program, but pass its addresses to the functions in a shared
> library that need it. (For instance, in more complex cases, to some
> initialization function for the shared library.) (Typically one
> doesn't do this for each separate variable needed to be handled like
> this, but collects them into some structure, of course, and passes the
> address of that struct to the shared library.)

Since you mentioned application and redesign - I thought I should explain what I
am trying to do. The application is a compiler, it's open source - url:
http://sourceforge.net/projects/xtcc filename qscript-0.7.tar.gz . I am using
C++/yacc to parse the input language and I compile to C++. I have a "runtime
library" and a "compile time" library. I think your suggestion to redesign the
application  is very valid in my case. The only barrier is that if I do static
linking, I do not have to change a single line in my program to compile on
windows - just document, for my end users, how to install the MinGW/MSYS
environment ( I am talking about users who are used to one click installs - so I
have put screenshots in my documentation for each stage etc).

> Anyway, to get the thing working as you want, below are modifications
> of your sample source files and a Makefile (just for MinGW in this
> case). Obviously your actual code will need ifdefs around the
> Windows-specific stuff (the __declspec decorations).

I had posted this question initially on stack overflow.

http://stackoverflow.com/questions/3686834/using-an-external-variable-in-c-in-a-shared-library-creating-a-shared-library


I have a request - can you please answer this question there with the same text
or Can I put a link on stack overflow to your answer here? Initially I thought
that the solution to this was trivial but that maybe I missed something in the
posts ( yes I did in a way - there is mention of the def file in the MinGW
documentation, but I could not piece it together), but "I think" not many people
seem to know how to do this (using the def file and dlltool)




------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: using an external variable in C++ in a shared library

Tor Lillqvist
> I have a request - can you please answer this question there with the same text
> or Can I put a link on stack overflow to your answer here?

OK, but I am not really a big fan of stackoverflow, the automated
"reputation" system is silly, and causes people with more spare time
than actual knowledge to gain "reputation".

--tml

------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
MinGW-users mailing list
[hidden email]

This list observes the Etiquette found at
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Loading...