Namespace std not recognized in public API.h for shared library

Pages: 12
It has been quite a while since I was working intermittently on my project to write a C++ shared library for Basex.
I finally managed to create a working combination of libBasexCpp.cpp and libBasexTest.cpp that compiles in Eclipse without problems. From libBasexCpp.cpp I am now trying to make a shared library.

I did not change anything to the source code of libBasexCpp.
For the API, I created a header file (libBasexCpp.h):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef LIBBASEXCPP_H
#define LIBBASEXCPP_H

using namespace std;

void Command(const std::string & command);
void Add(const std::string & path, const std::string & input);
void Create(const std::string & dbName, const std::string & content = "");
void Put(const std::string & path, const std::string & input);
void PutBinary(const std::string & path, const std::vector<std::byte>& input);
QueryObject * Query(const std::string & query, BasexSocket * socket);

QueryObject(const std::string &, BasexSocket *);
virtual ~QueryObject();
.
.
#endif // LIBBASEXCPP_H 


In libBasexTest.cpp, I replaced the includes to the local header files with
#include "include/libBasexCpp.h"

To build libBasexCpp.cpp, I use the following CMakeLists.txt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# Specify the minimum version.
cmake_minimum_required(VERSION 3.25.1)

# Specify the project info.
project(libBasexCpp VERSION 1.0.0 DESCRIPTION "LibBasexCpp library")

set(CMAKE_CXX_STANDARD 20)

add_library(${PROJECT_NAME} SHARED
  src/Basex.cpp
  src/BasexSocket.cpp
  src/BasexClient.cpp
  src/ClientUtils.cpp
  src/ResponseObj.cpp
  src/QueryObject.cpp
)

# Configure the directories to search for header files.
target_include_directories(${PROJECT_NAME} PRIVATE src)

set_target_properties(${PROJECT_NAME} PROPERTIES
  VERSION ${PROJECT_VERSION}
  SOVERSION ${PROJECT_VERSION_MAJOR}
  PUBLIC_HEADER include/libBasexCpp.h )

######## CURL STUFF ########
include(FindCURL)
find_package(CURL REQUIRED)
if(CURL_FOUND)
 message(STATUS "Found CURL version: ${CURL_VERSION_STRING}")
 message(STATUS "Using CURL include dir(s): ${CURL_INCLUDE_DIRS}")
 message(STATUS "Using CURL lib(s): ${CURL_LIBRARIES}")
else()
 message(FATAL_ERROR "Could not find CURL")
endif()

####### Install #########
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})


The following commands are executed without error messages:
1
2
3
4
5
cd Build
cmake ..
cmake --build .
cmake --install . --prefix /home/bengbers/lib
cd ..


The command:
gcc -L/home/bengbers/lib/lib64/libBasexCpp.so -Wall -o libTest libBasexTest.cpp -llibBasexCpp.so
returns this result:
1
2
3
4
5
6
7
8
9
10
11
include/libBasexCpp.h:6:25: error: 'string' in namespace 'std' does not name a type
    6 | void Command(const std::string & command);
      | ^~~~~~
include/libBasexCpp.h:1:1: note: 'std::string' is defined in header '<string>'; this is probably fixable by adding '#include <string>'
  +++ |+#include <string>
    1 | #ifndef LIBBASEXCPP_H
include/libBasexCpp.h:7:21: error: 'string' in namespace 'std' does not name a type
    7 | void Add(const std::string & path, const std::string & input);
      | ^~~~~~
.
.


It seems that the namespace 'std' is not recognized.

What should I do to be able to use the shared library though?

Translated with DeepL.com (free version)
Last edited on
It seems that the namespace 'std' is not recognized.

I don't see how you come to that conclusion.

You seem to be thinking that saying "using namespace std;" makes everything in the standard library available. It does not make anything available. It only allows you to use things in the standard library without saying std:: in front of them.

To get access to things in the standard library you need to include header files for the things you want. In this case you need to include the string header by saying "include <string>

It is generally considered a bad idea to say "using namespace std;" in a header file.
The error message is telling you what to do.
Try replacing "using namespace std;" with "include <string>" in libBasexCpp.h.
Last edited on
After removing `using namespace std'` and reinstalling the library, the following error is now `error: 'vector' in namespace 'std' does not call a template type`. This could be solved by adding #include <vector>. So I still think the problem has something to do with the std namespace.

I am indeed beginner in using C++. (This is also the beginner's forum). After programming in Basic, Pascal , PLSql, Fortran, Clipper and R, there was finally a need for me to learn C++. And I immediately admit that it is difficult. This is mainly because the documentation of C++ is not always very accessible.
I searched for a description of how to incorporate the public declarations from the local header files into the public API of the library. I did not find that description. Therefore, I simply copied the local public declarations. So that approach does not work.


How can I include the public declarations from the local header files in the library's API?
You sound defensive.
Fuck you.
So I still think the problem has something to do with the std namespace.

Don't ignore the errors the compiler spits out.

You insist on telling people with lots more experience than you have they don't know what they are telling you. The problem is not what you think it is.

You want to be able to use vectors and/or strings you need to include the headers for them. <vector> and <string>.

There are some headers that are implicitly included with other headers, but don't rely on that behavior. Explicitly include headers for C/C++ features you want to use.

You want others to help you stop rejecting the help.

I'm done trying since clearly you will refuse to understand what I've said.
simply understanding the error messages in c++ is also, unfortunately, a learning curve as they are frequently cryptic and use terms you may not have seen before. However, where it can, it tries to give you the offending file and line number where things went wrong. Always work off the topmost error as an error can create false errors after it where all that is wrong is that you already had something wrong. Missing ;s specifically can generate a ton of crap that is not really wrong.

That said this one isn't too bad. String is not a type... it can't find a definition for the type 'string' which is already been said to include the header for it; even the error message tells you this. Just trust for a bit and watch it start working, then understanding will follow behind as you get into the language for the first time.

namespace is a scope to group similar things. Using a namespace removes the scope qualifier (name::). The standard namespace wraps about 75% or so of the standard c++ tools into a common scope to prevent name collision of the thousands of items inside there with words you maybe wanted to use in your code and did not know was already in use. But removing the scope qualifier does not define these types and tools, as explained already. It looks like it would, given common english usage and other languages, but that isn't what the statement does.
Don't have using namespace .... (eg using namespace std;) in a header file. Always explicitly specify the required namespace in a header file. eg std::string, std::vector etc. For every library class/function etc that you use you need to also provide the required #include statement. eg #include <string>; #include <vector>; #include <iostream>; etc etc. Or since C++20/23 use import std;

For a beginners tutorial on C++ see:
https://www.learncpp.com/
As DizzyDon advised, I removed
using namespace std;
and inserted
#include <string> #include <vector> #include <list> and #include <cstddef>
into libBasexCpp.h. This solved many error messages.
After I read somewhere else that you should first create an object file using the command gcc -I ./include -c src/libBasexTest.cpp I saw that all remaining error messages were related to missing object types defined in the local header files. For example Class names (like QueryObject in line 11) or types defined with typedef are missing.

The original source code compiled in Eclipse without error messages. So I assume in the cpp. and h. files there are no errors.
After copying the source code to a new directory I was able to create an so. file without problems using CMake --build and cmake --install.
Compiling libBasexTest.cpp gives error messages all stemming from errors in libBasexCpp.h

So creating libBasexCpp.h is clearly more complicated than copying the public declarations from the local header files into 1 overarching API file.
Therefore, in my response to DizzyDon's answer, I asked where I can find instructions on creating such an API header file.

Ben
Jonnin and seeplus are thanked for the explanation, by the way.

EDIT

After adding the missing #includes <> and adding these typedefs
1
2
typedef std::vector<std::vector<std::byte>> VectOfByteVect;
typedef std::vector<std::byte>              ByteVect;

all <missing type> errors are gone.

The remaing errors are all related to missing class objects.

My project uses 5 classes: Base, BasexSocket, BasexClient, OueryObject and ResponseObject. Most classes have public and private methods.

This is part of the header file for Base:
1
2
3
4
5
6
class Base {
public:
  Base(const std::string&, const std::string&, const std::string&, const std::string&);
  Base(BasexSocket * socket);
  virtual ~Base();
  ...
.
And this is part of the header file for BasexClient:
1
2
3
4
5
6
7
8
9
10
11
12
13
using namespace std;

class BasexClient : public Base {
  public:
    BasexClient (const std::string&, const std::string&, const std::string&, const std::string&);
    virtual ~BasexClient();
    void Command(const std::string & command);
    void Create(const std::string & dbName, const std::string & content = "");

  private:
    ResponseObj Response;
  ...
};

I only want to add to add the public methods from BasexClient, QueryObject and ResponseObject to the library header.

I created a new libBasexCpp.h, copied all the class definitions from the local header files to libBasexCpp.h and deleted all the private members.
I have been experimenting a lot but no mather what I do, every time that a function returns of uses an instance of one of my classes, the compiler still complains about missing types.

How can I define the classes in the API? Is using the Pimpl idiom really the only way to solve this?
Last edited on
Compiling libBasexTest.cpp gives error messages all stemming from errors in libBasexCpp.h


What are the first few? C++ is notorious for generating multiple errors from a simple issue. I once get a few hundred errors from a misplaced } !

[<user>@fedora libBasexCpp]$ -I ./include/ -c libBasexTest.cpp
In file included from libBasexTest.cpp:13:
include/libBasexCpp.h:20:33: fout: expected class-name before ‘{’ token
20 | class BasexClient : public Base {
| ^
include/libBasexCpp.h:29:5: fout: ‘QueryObject’ does not name a type
29 | QueryObject * Query(const std::string & query);
| ^~~~~~~~~~~
include/libBasexCpp.h:30:5: fout: ‘QueryObject’ does not name a type
30 | QueryObject * Query(const std::string & query, BasexSocket * socket);
| ^~~~~~~~~~~
include/libBasexCpp.h:39:33: fout: expected class-name before ‘{’ token
39 | class QueryObject : public Base {
| ^
...
libBasexTest.cpp: In function ‘int main()’:
libBasexTest.cpp:38:42: fout: ‘class BasexClient’ has no member named ‘Query’
38 | QueryObject * Q_Object = Session.Query(AddBook);
| ^~~~~
libBasexTest.cpp:55:28: fout: ‘class BasexClient’ has no member named ‘Query’
55 | Q_Object = Session.Query(query);
| ^~~~~
libBasexTest.cpp:63:28: fout: ‘class BasexClient’ has no member named ‘Query’
63 | Q_Object = Session.Query(query);
| ^~~~~
libBasexTest.cpp:71:28: fout: ‘class BasexClient’ has no member named ‘Query’
71 | Q_Object = Session.Query(query);
| ^~~~~
Last edited on
From the first error it looks like the compiler doesn't know about class Base. Where is this class defined? It needs to be before its use. If it's defined in another header then this header file needs to be included. If it's defined in the same header file then it needs to be before BasexClient is defined.

I inserted this as the first class definition:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Base {
public:
  Base(const std::string&, const std::string&, const std::string&, const std::string&);
  Base(BasexSocket * socket);
  virtual ~Base();

  Base& addVoid(std::string Add, std::vector<std::byte> & To);
  Base& addVoid(std::vector<std::byte> Add, std::vector<std::byte> &To);
  Base& pushByte(unsigned char Oct, std::vector<std::byte> &To);
  Base& handShake(std::vector<std::byte> Input, std::vector<std::byte> & Result);

  BasexSocket * Socket;
  BasexSocket * getSocket();
};


This is the result: (These are all the errors related to libBasexCpp.h)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<user>@fedora libBasexCpp]$ -I ./include/ -c libBasexTest.cpp
In file included from libBasexTest.cpp:13:
include/libBasexCpp.h:24:19: fout: expected ‘)’ before ‘*’ token
   24 |   Base(BasexSocket * socket);
      |       ~           ^~
      |                   )
include/libBasexCpp.h:32:3: fout: ‘BasexSocket’ does not name a type
   32 |   BasexSocket * Socket;
      |   ^~~~~~~~~~~
include/libBasexCpp.h:33:3: fout: ‘BasexSocket’ does not name a type
   33 |   BasexSocket * getSocket();
      |   ^~~~~~~~~~~
include/libBasexCpp.h:45:5: fout: ‘QueryObject’ does not name a type
   45 |     QueryObject * Query(const std::string & query);
      |     ^~~~~~~~~~~
include/libBasexCpp.h:46:5: fout: ‘QueryObject’ does not name a type
   46 |     QueryObject * Query(const std::string & query, BasexSocket * socket);
      |     ^~~~~~~~~~~
include/libBasexCpp.h:57:42: fout: ‘BasexSocket’ has not been declared
   57 |         QueryObject(const std::string &, BasexSocket *);
      |                                          ^~~~~~~~~~~
include/libBasexCpp.h:81:3: fout: ‘ResponseObj’ does not name a type
   81 |   ResponseObj     Response;
      |   ^~~~~~~~~~~


EDIT

After seeing that the order in which classes were definded was relevant, I changed the order in which they were defined:
1: BasexSocket
2: Base
3: ResponseObj
4: QueryObject
5: BasexClient

There are no errors anymore and an object file is created!

Thanx!
Last edited on
Is this all in 1 file, or is there a header file for each class (preferred).

Since the class Base declaration only uses BasexSocket as a pointer (this would also apply to references), you only need to forward declare BasexSocket before Base.

I would recommend putting your Base declaration into a file named Base.h, and just before (but inside your include guards) simply declare class BasexSocket;. Then you don't have to worry about what order header files are included by the source files. And if another source file needs to include Base.h but not BasexSocket.h, you don't have to worry about a thing.

In the original code I had separate header files for each class. But now you are confusing me. I thought it was mandatory for a shared library to aggregate all methods that are public into one API header file?
Is this assumption wrong?

And can you explain what you mean with "forward declare BasexSocket before Base"? I didn't start learning C++ until I was 68 years old and I still feel like a beginner. I am still learning but it does take more effort than before and extra explanations are much appreciated. :-)

CMake installs the so. - files as expected in ~/lib but no matter what I try, despite all the variations on the path to ~/lib, `gcc -L /home/bengbers/lib -o myTest libBasexTest.o -llibBasexCpp.so` keeps complaining that libBasexCpp.so cannot be found.
This is the next problem I can wrap my head around ;-) (Is this correct English?)
forward declaration is a thing in c++ and it uses to tell the compiler that "this will exist, I promise" before the compiler has yet seen it.

like this:

class forward; //promises that a real class forward will be along someday.

It is still limited in usefulness, but it can get you past many chicken and egg problems.

you can read more than you wanted to here: https://stackoverflow.com/questions/4757565/what-are-forward-declarations-in-c

pay attention to this section:
Break cyclic references where two definitions both use each other


----------------------
Ill be the unix hater here and wonder if moving to visual studio on windows might help you with the language. Trying to learn makefiles and unix nonsense on top of c++ may be overwhelming-- its critical, important stuff to know, but perhaps another day? Visual studio and windows approaches remove a great deal of the complexity for building a working, running program by hiding the compile details from you. This has pros and cons, but for a beginner, far more pros than cons.

Last edited on
Consider the following 2 header files:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef A_CLASS
#define A_CLASS

#include "B.h"

class A
{
public:
    B* createObjectB();

private:
    int x;
};
#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef B_CLASS
#define B_CLASS

#include "A.h"

class B
{
public:
    A* createObjectA();

private:
    double y;
};
#endif 


With this code, A.h inlcude B.h and vice versa. Both depend on each other.

If you change the #include statements to:
class B;
or
class A;
then the dependency cycle is broken, and compilation can continue. The forward declaration (e.g. class A;) can be used when the header file needs to know that there IS a class A, but does not care what class A contains. Like in the case of only using A* or A&.

And in the case, if a source file down the road needs functionality from class A but not class B, the programmer only needs to include "A.h". There is no dependency (or need to even know about) "B.h". This makes code more robust.
I developed most of the original source code in Eclipse. And in the past I have looked at the extent to which the linux version of Visual Studio was usable. Both development environments are quite usable but both take a lot of time to figure out how to set all the options properly.
I have been working with Linux (RedHat 4.2) since the mid-1980s and have gotten used to the fact that it sometimes takes a long time to get things working. But that makes it fun ;-)
It does not make much difference whether I work with Windows or Linux, on both platforms I can usually do what is needed. The advantage of Linux is that I can use the prompt, I always have the impression that the prompt gives me more options. And it may be because of my age or my scientific education but I always want to find out first what to expect as a result of my actions. And in doing so, I have more options under Linux.

I can now test the C++ version of the shared library. The test program gives the same output as the original version in Eclipse.
The only difference is that the program now ends with the error message:
1
2
double free or corruption out
Aborted (made memorydump)


Figuring out what that means will be the next puzzle.
Its fine if you want to do it, was just a suggestion in case the unix builds were adding to your difficulties. If you have a strong unix background, keep going as you were.

the message suggests you tried to free memory twice.
you can clear that by either not doing it, or by ensuring that when you free/delete etc memory, you set any pointers involved to nullptr. Releasing a nullptr is safe and no warning/error, though its also pointless so while its a type of defensive programming and good practice, its better to not double release just because.. it a little sloppy.

I also can't live without a prompt. The windows one will do a lot, but I have merged cygwin's into my standard cmd window so I can use unix commands at my 'dos' prompt. cygwin is a unix environment under windows; I use a handful of unix commands like grep and also use it to compile c++ as if linux to test portability and such.
Last edited on
double free or corruption


You could be trying to free memory after it has already been freed. Or it could be that you're trying to use unallocated memory (eg trying to access past last allocated). Are you using c-style null-terminated strings? Also remember that array access starts at 0 and the last valid access is one less than the size.

If you're using new/delete then consider using managed pointers with std::unique_ptr and std::shared_ptr. These are RAII and will automatically release allocated memory when they go out of scope. See also std::make_unique

https://en.cppreference.com/w/cpp/memory/unique_ptr
https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
After installing Linuxtools for Eclipse, I was able to use valgrind on my testcode.

Yesterday - before applying the updates on my machine - valgrind reported that it had found 2 dangling bytes. This was related to these lines:
1
2
3
4
Base::Base(const std::string& DBHOST, const std::string & DBPORT,
           const std::string & DBUSERNAME, const std::string & DBPASSWORD)
           : Socket(new BasexSocket(DBHOST, DBPORT, DBUSERNAME, DBPASSWORD)){};
Base::Base(BasexSocket * socket) { Socket = socket;};

I inspected my code and I saw that I din't explicitly release the memory.
Today - after updating - valgrind found no problems???

Yesterday, I found that a lot of memory problems could be avoided by using std::unique pointers. I more or less understand the explanation I found on cppreference.com, but I don't see how I can use this in my code.

Is it wise to change my code and use the unique pointers (even though valgrind does not report errors) or is it best to leave the code as it is?
If I should use the unique pointers, how can they be used in the initialization list?

(Or is it better to start a new thread with this question)?

Ben
Last edited on
Pages: 12