Here's my includes:
#include <iostream>
#include <string>
#include <cstring>
#include <stdio.h> //for snprintf
#include <libscrypt.h>
#include <sqlite3.h>
#include "generator.h" //has no dependencies
And here's my g++ 4.2.1 command with compilation errors:
# g++ -I/usr/local/include -L /usr/local/lib test.cpp generator.cpp -o test -lscrypt -lsqlite3
/tmp//cctxmw4C.o: In function `insertUser()':
test.cpp:(.text+0x607): undefined reference to `libscrypt_salt_gen(unsigned char*, unsigned long)'
test.cpp:(.text+0x6c3): undefined reference to `libscrypt_scrypt(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned long long, unsigned int, unsigned int, unsigned char*, unsigned long)'
collect2: ld returned 1 exit status
Similar C code compiles fine with GCC. I do not believe that the order of the parameters is the problem -- I have tried multiple variations, including moving the -I, -L, and both -l flags. Both scrypt and sqlite3 are C libraries, and sqlite3 throws no errors despite having the header and shared library in -I and -L respectively.
Look at the solution here.
Using C Libraries for C++ Programs
extern "C"{
void c_function_prototype();
}
or
extern "C" void c_function_prototype();
If you have it see "The C++ Programming Language (Stoustrup) 4th Edition" p429
Related
I have a function in C++ that uses data types like vector and map from STL. Here is some sample code:
mylib.cpp
#include "mylib.h"
#include<vector>
using namespace std;
int summation(int n) {
vector<int> numbers;
int sum = 0;
for(int i = 1; i <=n; i++)
numbers.push_back(i);
for(int j = 0; j < numbers.size(); j++)
sum += numbers[j];
return sum;
}
I created a header file as follows:
mylib.h
#ifdef _cplusplus
extern "C" {
#endif
extern int summation(int n);
#ifdef _cplusplus
};
#endif
The C++ file was compiled into the obejct code using the command
g++ -o mylib.o -c mylib.cpp
Then, I wrote a C program in order to use the function summation from it.
main.c
#include<stdio.h>
#include "mylib.h"
int main() {
int n;
scanf("%d", &n);
printf("%d", summation(n));
return 0;
}
Now, when I compile the C file above using gcc,
gcc main.c mylib.o
I get the following error
/tmp/ccAMN2ld.o: In function `main':
main.c:(.text+0x33): undefined reference to `summation'
mylib.o: In function `std::vector<int, std::allocator<int> >::_M_insert_aux(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&)':
mylib.cpp:(.text._ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi[_ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi]+0x26e): undefined reference to `__cxa_begin_catch'
mylib.cpp:(.text._ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi[_ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi]+0x2d7): undefined reference to `__cxa_rethrow'
mylib.cpp:(.text._ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi[_ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi]+0x2df): undefined reference to `__cxa_end_catch'
mylib.o: In function `std::vector<int, std::allocator<int> >::_M_check_len(unsigned long, char const*) const':
mylib.cpp:(.text._ZNKSt6vectorIiSaIiEE12_M_check_lenEmPKc[_ZNKSt6vectorIiSaIiEE12_M_check_lenEmPKc]+0x5b): undefined reference to `std::__throw_length_error(char const*)'
mylib.o: In function `__gnu_cxx::new_allocator<int>::deallocate(int*, unsigned long)':
mylib.cpp:(.text._ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim[_ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim]+0x1c): undefined reference to `operator delete(void*)'
mylib.o: In function `__gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*)':
mylib.cpp:(.text._ZN9__gnu_cxx13new_allocatorIiE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorIiE8allocateEmPKv]+0x2c): undefined reference to `std::__throw_bad_alloc()'
mylib.cpp:(.text._ZN9__gnu_cxx13new_allocatorIiE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorIiE8allocateEmPKv]+0x3c): undefined reference to `operator new(unsigned long)'
mylib.o:(.eh_frame+0x4b): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status
It is imperative that I use gcc to compile the C file. Is there a way to make it work?
I tried looking for solution and stumbled upon the links below,
How to call C++ function from C?
Elegantly call C++ from C
http://www.cplusplus.com/forum/general/8997/
but couldn't find a solution to my problem.
Compile the C file by itself with the C compiler:
gcc -c cfile.c
then link all the files with the C++ compiler:
g++ -o a.out main.o cfile.o mylib.o
Note that you must compile the file with the main function with the C++ compiler. Any other files can be compiled with either, though you need extern "C" declarations to be able to call C code from C++ or create C++ functions that can be called from C
I have build all the file in g++, am not getting linking error. can you build all the source file to gcc or g++.
So I recently started using a library called libgambatte (github), everything was going just fine until the linker started complaining about an undefined reference for a method. What's really strange is that it find every other method for that object! Arguments' types are correct (I've copied them from the working program included with the library).
Here's the code:
Make output:
g++ -Wall -Wextra -g3 -I../libgambatte/include -I../common -c -o test.o test.cpp
g++ test.o -L../libgambatte -lgambatte -lz -o test
test.o: In function `main':
<REDACTED>/src/test.cpp:12: undefined reference to `gambatte::GB::runFor(unsigned long*, long, unsigned long*, unsigned long&)'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'test' failed
make: *** [test] Error 1
Makefile:
CPPFLAGS=-Wall -Wextra -g3 -I../libgambatte/include -I../common
LDFLAGS=-L../libgambatte -lgambatte -lz
.PHONY=all clean
all: test
test: test.o
$(CXX) test.o $(LDFLAGS) -o test
clean:
rm -f test.o test
Output of nm ../libgambatte/libgambatte.a | grep runFor:
0000000000007a20 T _ZN8gambatte3CPU6runForEm
0000000000000190 T _ZN8gambatte2GB6runForEPjlS1_Rm
U _ZN8gambatte3CPU6runForEm
Source for test.cpp:
#include <gambatte.h>
using namespace std;
int main(void){
gambatte::uint_least32_t audiobuf[1234];
gambatte::uint_least32_t framebuf[1234];
size_t samples = 1234;
unsigned gb_width = 160;
gambatte::GB gb;
gb.runFor(framebuf, gb_width, audiobuf, samples);
return 0;
}
runFor method declaration:
std::ptrdiff_t runFor(gambatte::uint_least32_t *videoBuf, std::ptrdiff_t pitch,
gambatte::uint_least32_t *audioBuf, std::size_t &samples);
Definition for gambatte::uint_least32_t:
#ifdef HAVE_CSTDINT
#include <cstdint>
namespace gambatte {
using std::uint_least32_t;
using std::uint_least16_t;
}
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
namespace gambatte {
using ::uint_least32_t;
using ::uint_least16_t;
}
#else
namespace gambatte {
#ifdef CHAR_LEAST_32
typedef unsigned char uint_least32_t;
#elif defined(SHORT_LEAST_32)
typedef unsigned short uint_least32_t;
#elif defined(INT_LEAST_32)
typedef unsigned uint_least32_t;
#else
typedef unsigned long uint_least32_t;
#endif
#ifdef CHAR_LEAST_16
typedef unsigned char uint_least16_t;
#else
typedef unsigned short uint_least16_t;
#endif
}
#endif
Sorry for the long code.
I've found the problem: as you can see in the definition of gambatte::uint_least32_t, the type definition is based on the presence of certain constants. My problem manifested because the library (and the included program) are compiled with -DHAVE_STDINT_H and therefore define gambatte::uint_least32_t as a different type, causing the linker to not find the correct signature; compiling with -DHAVE_STDINT_H solved the problem for me.
I have install leveldb in my home directory ~/local like this.
[~/temp/leveldb-1.15.0] $ make
[~/temp/leveldb-1.15.0] $ cp -av libleveldb.* $HOME/local/lib/
[~/temp/leveldb-1.15.0] $ cp -av include/leveldb $HOME/local/include/
My c++ program like this:
#include <assert.h>
#include <iostream>
#include "leveldb/db.h"
using namespace std;
int main(int argc,char * argv[])
{
leveldb::DB* db;
leveldb::Options options;
options.create_if_missing = true;
std::string dbpath = "tdb";
leveldb::Status status = leveldb::DB::Open(options, dbpath, &db);
assert(status.ok());
std::string key1 = "grz";
std::string key2 = "grz-rt#63.com";
cout<<"Open db OK"<<std::endl;
std::string value;
leveldb::Status s ;
s = db->Put(leveldb::WriteOptions(), key1, key2);/*key1和key2作为一对key-value对插入*/
s = db->Get(leveldb::ReadOptions(), key1, &value);/*根据key返回对应的value值*/
cout<<value<<std::endl;
delete db;/*删除数据库*/
return 0;
}
I compile this C++ program like this:
g++ -o Main Main.cpp ~/local/lib/libleveldb.a -lpthread -I ~/local/include/
But I get the error like this:
/public/home/kli/local/lib/libleveldb.a(table_builder.o): In function `leveldb::TableBuilder::WriteBlock(leveldb::BlockBuilder*, leveldb::BlockHandle*)':
table_builder.cc:(.text+0x678): undefined reference to `snappy::MaxCompressedLength(unsigned long)'
table_builder.cc:(.text+0x6b2): undefined reference to `snappy::RawCompress(char const*, unsigned long, char*, unsigned long*)'
/public/home/kli/local/lib/libleveldb.a(format.o): In function `leveldb::ReadBlock(leveldb::RandomAccessFile*, leveldb::ReadOptions const&, leveldb::BlockHandle const&, leveldb::BlockContents*)':
format.cc:(.text+0x5de): undefined reference to `snappy::GetUncompressedLength(char const*, unsigned long, unsigned long*)'
format.cc:(.text+0x64e): undefined reference to `snappy::RawUncompress(char const*, unsigned long, char*)'
collect2: ld returned 1 exit status
I don't know what's wrong.
I am new to Linux. Thank you very much!
libleveldb.a misses Snappy when being linked which would be probably in libsnappy.a in the same directory.
Looks like the Makefile is incomplete.
With the current install, you need to edit the Makefile to link against snappy and to include -L/usr/local/lib instead of -L/usr/local/include.
(Will post pull request later)
I am trying to link my program with libjpeg.
arm-mandriva-linux-gnueabi-g++ v4l2grab2.cpp -o v4l2grab -Wall -Llib -ljpeg
Errors:
v4l2grab2.cpp:(.text+0xa28): undefined reference to `jpeg_std_error(jpeg_error_mgr*)'
v4l2grab2.cpp:(.text+0xa44): undefined reference to `jpeg_CreateCompress(jpeg_compress_struct*, int, unsigned int)'
v4l2grab2.cpp:(.text+0xa54): undefined reference to `jpeg_stdio_dest(jpeg_compress_struct*, _IO_FILE*)'
v4l2grab2.cpp:(.text+0xa88): undefined reference to `jpeg_set_defaults(jpeg_compress_struct*)'
v4l2grab2.cpp:(.text+0xaa4): undefined reference to `jpeg_set_quality(jpeg_compress_struct*, int, int)'
v4l2grab2.cpp:(.text+0xab4): undefined reference to `jpeg_start_compress(jpeg_compress_struct*, int)'
v4l2grab2.cpp:(.text+0xaf0): undefined reference to `jpeg_write_scanlines(jpeg_compress_struct*, unsigned char**, unsigned int)'
v4l2grab2.cpp:(.text+0xb1c): undefined reference to `jpeg_finish_compress(jpeg_compress_struct*)'
v4l2grab2.cpp:(.text+0xb28): undefined reference to `jpeg_destroy_compress(jpeg_compress_struct*)'
But, when i rename the file to *.c and try to compile it with arm-mandriva-linux-gnueabi-gcc (instead of g++) everything works!
I really need to use it inside C++ code.
How can I compile this code with g++?
It seems you are including a C header without C++ support. Try including the relevant header from within an extern "C" block:
extern "C" {
#include <jpeglib.h>
}
(since you didn't post any code I'm not sure which header you try to include and just guessed <jpeglib.h>).
In case you need to include <jpeglib.h> from a header which should also be viable to be included from C, you'd wrap it with a test for C++:
#ifdef __cplusplus
extern "C" {
#endif
#include <jpeglib.h>
#ifdef __cplusplus
}
#endif
I can create .o file with g++ -c test.cpp -std=c++0x, but cant link it, got next errors:
test.cpp:(.text+0xe5): undefined reference to `std::regex_iterator<char const*, char, std::regex_traits<char> >::regex_iterator(char const*, char const*, std::basic_regex<char, std::regex_traits<char> > const&, std::bitset<11u>)'
test.cpp:(.text+0xf1): undefined reference to `std::regex_iterator<char const*, char, std::regex_traits<char> >::regex_iterator()'
Code:
#include <regex>
#include <iostream>
#include <string.h>
typedef std::regex_iterator<const char *> Myiter;
int main()
{
const char *pat = "axayaz";
Myiter::regex_type rx("a");
Myiter next(pat, pat + strlen(pat), rx);
Myiter end;
return (0);
}
The GNU C++ standard library supports <regex>, but not until version 4.9.0. (The headers were present in earlier versions, but were unusable.)
The other compilers don't support it, as far as I can see.
You can use a different library if you use an older GCC.