LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 08-14-2003, 11:23 AM   #1
Gethyn
Member
 
Registered: Aug 2003
Location: UK
Distribution: (X)Ubuntu 10.04/10.10, Debian 5, CentOS 5
Posts: 900

Rep: Reputation: 32
C++: How to use a namespace in a user-defined library?


I'm attempting to write a program using a small library of functions I've written (in fact so small that it currently only includes one function!). I've put the library function(s) inside a namespace, with a view to expanding it later. The library header and its implementation file are compiling and linking OK. The main program file (which is rather unimaginatively called test.cpp at the moment) is also compiling correctly, but when it comes to linking, the linker gives the message:

ld: Undefined symbols:
normalRand()

(normalRand() is the name of the library function inside the namespace).

Now, i'm pretty sure that I've included all the correct header files. I've qualified the namespace correctly in test.cpp. I just can't see what's going wrong! Is there something that needs to be added to the Makefile when you want to include a user-defined library as opposed to including a Class (as an aside: I've written several Classes and used these in test.cpp, and they all work perfectly)? I'm compiling using gcc.

I have to say, at this stage using a namespace isn't exactly necessary, or very important, but it's really annoying me that it's not working when I think I've done everything right!

If it makes things any clearer I can easily send you (or post on here) the source code and the Makefile. Thanks if you can help!
 
Old 08-14-2003, 12:12 PM   #2
tmulcahy
LQ Newbie
 
Registered: Aug 2003
Posts: 1

Rep: Reputation: 0
Hi Gethyn,
I think your problem may be in your Makefile. When you have multiple .cpp files your Makefile should first create one object file (extension usually .o) for each source file. Then your Makefile can link them together. Here's the code to do this at the command line. If you post your Makefile I can help you fix that up too.

Code:
g++ -c library.cpp
g++ -c test.cpp
g++ library.o test.o -o test
The first two lines create object files for each source. The third takes the two object files (library.o and test.o) and makes an executable: test. You have to tell the compiler where to find the definition for your library function.

By the way, if you decide to not use Makefiles (it's good to learn Makefiles, but if you are doing such a simple project, it might be simpler for you to just compile at the command line and not worry about Makefile syntax for now) here is the simplest way to compile - this skips the step of creating object files:

Code:
g++ library.cpp test.cpp -o test
 
Old 08-14-2003, 12:35 PM   #3
alaric
LQ Newbie
 
Registered: Aug 2003
Location: Amsterdam
Distribution: debian
Posts: 12

Rep: Reputation: 0
A namespace can be considered to be a postfix of variables
and functions etc. However, instead of writing:

coollib_rotate

you write

coollib::rotate

Not using any prefix would give namespace
pollution; the words in the dictionary will be used
up very quickly and very often functions of different
libraries would collide.

The prefix used by standard C libraries is an
underscore. User application should therefore not
use leading underscores, and are then garanteed
not to run into collisions, if they only link with standard
libraries.

When writing a library yourself, then this problem still
exists; you can't just like that start to use underscores
of course.

A C library would use a clearly recognizable prefix, like
the coollib_ above.

The problem with those prefixes is that you have to
type a lot.

So, what is the difference with namespaces? You might
ask. Because typing coollib::
is even a character more!

Well, the difference is that inside a given namespace
you don't have to write that prefix anymore. And, users of
that namespace don't have to re-type the prefix either all
the time: they can include names from a given namespace
into their current namespace with the using declarator.

For example, when you defined

namespace mylib {
  int foo;
}


and someone elses library at the same
time defined

namespace theirlib {
  char foo;
}


Then a user of the libraries, while working inside
any namespace, for example 'work', can incorporate
mylib::foo inside his current namespace:

namespace work {
  using mylib::foo; // Puts mylib::foo inside work.

  int i = foo; // uses work::foo, which is equal to mylib::foo because of the 'using' above.
}


You will understand that you never want to put
a using declarator inside
a namespace that is not yours! For example, never
put a using inside the root namespace ':: '.

Rule of thumb: Don't use a using declarator inside the header of your library.

Ok, now a full example of a library that defines a
function foo inside namespace coollib :

coollib.h:

namespace coollib {
  void foo(void);
}


coollib.cc:

#include "coollib.h"

namespace coollib {
  void foo(void)
  {
    // ...
  }
}


User of your library:

#include "coollib.h"

int main(void)
{
  coollib::foo();

  // Or
  using coollib::foo;
  foo();
}


Carlo Wood
[Not a newbie, as linuxquestions.org seems to think]

Last edited by alaric; 08-14-2003 at 12:41 PM.
 
Old 08-14-2003, 05:05 PM   #4
dakensta
Member
 
Registered: Jun 2003
Location: SEUK
Distribution: Debian & OS X
Posts: 194

Rep: Reputation: 35

Is there something that needs to be added to the Makefile when you want to include a user-defined library ...


You are linking to your library when you create the executable, aren't you?

g++ test.cpp -o myapp -L/dir/containing/your/lib -lnrand

where your library is something like libnrand.a (or .so)
(that is an upper case and then lower case letter L in case it is not clear)

Just checking the obvious things first

Next check that your library compiles and links to the executable without using a namespace for the funtions. Just comment out the namespace scope in the header and implementation files and post back to let us know how that goes.
 
Old 08-15-2003, 04:15 AM   #5
Gethyn
Member
 
Registered: Aug 2003
Location: UK
Distribution: (X)Ubuntu 10.04/10.10, Debian 5, CentOS 5
Posts: 900

Original Poster
Rep: Reputation: 32
Thanks guys, but i haven't managed to get round the problem. (to be honest i didn't understand the last post!)

I'm gonna put up my source code and Makefile to try and clarify things a bit.

Makefile:

CPPFLAGS = -Wall -Dlinux -Wno-unused -traditional-cpp

test : test.o particle.o coordinate.o direction.o jpdmclib.o
gcc -o test test.o particle.o coordinate.o direction.o \
jpdmclib.o -L/sw/lib -ldl -lstdc++

test.o : test.cpp particle.h coordinate.h direction.h jpdmclib.h
gcc -c ${CPPFLAGS} test.cpp
particle.o : particle.cpp particle.h coordinate.h direction.h
gcc -c ${CPPFLAGS} particle.cpp
coordinate.o : coordinate.cpp coordinate.h
gcc -c ${CPPFLAGS} coordinate.cpp
direction.o : direction.cpp direction.h
gcc -c ${CPPFLAGS} direction.cpp
jpdmclib.o : jpdmclib.cpp jpdmclib.h
gcc -c ${CPPFLAGS} jpdmclib.cpp

Obviously, "test" is the main program. "jpdmclib" is the library i'm trying to include (the last post seems to suggest that i'm not using the right file type for this but i don't understand that so if anyone can explain that would also be helpful!). The other object files are classes that I've written. Before i tried to include jpdmclib the program was compiling and linking just fine (and even giving the correct output ^_^).

The header for jpdmclib goes as follows:

Code:
//jpdmclib.h

#ifndef JPDMCLIB_H
#define JPDMCLIB_H

namespace JPDMonteCarloFunctions
{
    double normalRand();
}

#endif // JPDMCLIB_H ///:~
and its implementation looks like this:

Code:
//jpdmclib.cpp

#include "jpdmclib.h"
#include <cstdlib>

namespace JPDMonteCarloFunctions
{
    double normalRand()
    {
        const double normaliser = RAND_MAX;
        double random = rand();
        double normRand = random / normaliser;
        return normRand;
    }
}
I'm well and truly confused because this seems to be following all the examples i've seen in books etc. It's not exactly complicated! I plan to expand it as the project progresses but obviously I'd like to get this side of it working before putting in much time to writing more functions!

Here's the error i get from the linker:

$ make
gcc -c -Wall -Dlinux -Wno-unused -traditional-cpp jpdmclib.cpp
gcc -o test test.o particle.o coordinate.o direction.o \
jpdmclib.o -L/sw/lib -ldl -lstdc++
ld: Undefined symbols:
normalRand()
make: *** [test] Error 1

Hope this makes things clearer! Thanks again

Last edited by Gethyn; 08-15-2003 at 05:02 AM.
 
Old 08-15-2003, 04:17 AM   #6
Gethyn
Member
 
Registered: Aug 2003
Location: UK
Distribution: (X)Ubuntu 10.04/10.10, Debian 5, CentOS 5
Posts: 900

Original Poster
Rep: Reputation: 32
A quick note to dakensta: sorry, shoulda mentioned this in the last post, i've already tried commenting out the namespace and calling the function using the global scope, that works just fine.
 
Old 08-15-2003, 04:44 AM   #7
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 50
firstly, this doesnt really have anything to do with libraries, libraries are either static archives produced by ar or shared objects produced by gcc -shared -fPIC ..., jdbmclib.o is just another plain object file not a library. it seems your problem is with namespaces.

try this for the cpp file:

Code:
#include "jpdmclib.h"
#include <cstdlib>

//for rand() and RAND_MAX
using namespace std;

namespace JPDMonteCarloFunctions
{
    double normalRand()
    {
        const double normaliser = RAND_MAX;
        double random = rand();
        double normRand = random / normaliser;
        return normRand;

        //just an idea??
        //return ((double)rand() / RAND_MAX);
    }
}
and to call the function call it like
Code:
JPDMonteCarloFunctions::normalRand();
if i remember my c++ that should be right, oh and use g++ instead of gcc -lstdc++

Last edited by kev82; 08-15-2003 at 05:10 AM.
 
Old 08-15-2003, 05:09 AM   #8
Gethyn
Member
 
Registered: Aug 2003
Location: UK
Distribution: (X)Ubuntu 10.04/10.10, Debian 5, CentOS 5
Posts: 900

Original Poster
Rep: Reputation: 32
It still isn't working. Thanks for the suggestions, i'm using g++ now instead of gcc but it doesn't seem to make any difference (I realise that was a separate issue but you can always hope!). I've defined the namespace and the function in exactly the way you described, and been using the scope resolution to call the function correctly all along, but it still doesn't recognise it.
 
Old 08-15-2003, 05:15 AM   #9
Gethyn
Member
 
Registered: Aug 2003
Location: UK
Distribution: (X)Ubuntu 10.04/10.10, Debian 5, CentOS 5
Posts: 900

Original Poster
Rep: Reputation: 32
Scratch that, i just realised that normalRand is called in one of the other .cpp files (which is why i put it in a file of its own in the first place), and i'd forgotten to put the scope resolution in there. Doh! Thanks very much for the help
 
Old 08-15-2003, 05:29 AM   #10
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 50
<edit> that'll teach me not to refresh my window before i do a long post, lol

Last edited by kev82; 08-15-2003 at 05:31 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to send user defined signal in linux feetyouwell Linux - Software 6 12-26-2007 04:40 AM
User defined protocols with Guarddog Shafted Linux - Security 4 09-01-2005 12:56 PM
how to define user-defined commands in linux mannoulla Linux - General 1 04-05-2005 09:01 PM
user defined variables linuxdev Linux - Newbie 4 02-09-2004 12:43 PM
Squirrelmail: How can I load user defined themes? DJ_Cyberdance Linux - Software 0 12-12-2003 04:40 PM


All times are GMT -5. The time now is 06:14 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration