I'm trying to use libreDWG to open and understand some dwg files. I have installed it and at least got some of the test programs to run (even if they seg fault later on). Anyway, I have included a small header file in my project very similar to the simple example found here https://github.com/h4ck3rm1k3/libredwg/blob/master/examples/load_dwg.c There seems to be a general problem with data types (at least in the way I'm compiling it) meaning I've added a few casts of form (char*) to number of variables which previously trying to automatically convert (void*) and (unsigned char*) to type (char*) and got rid of those compiler complaints. But even still when I compile it like so
g++ xxx.c++ -L/opt/local/lib/ -lredwg -o program_name
I get the following error:
Undefined symbols for architecture x86_64:
"dwg_read_file(char*, _dwg_struct*)", referenced from:
load_dwg(char*)in ccN6HUqz.o
"dwg_free(_dwg_struct*)", referenced from:
load_dwg(char*)in ccN6HUqz.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
I'm not sure what to do, I've fixed any problems in the source the compiler complains about and am linking to the relevant libraries with -lredwg (right? I haven't missed any?). My header file is just to test the functionality and looks like:
#include "suffix.c"
#include <dwg.h>
plan floor_plan;//temporary data structure defined elsewhere for now
void
add_line(double x1, double y1, double x2, double y2)
{
line_in temp;
temp.start.x=x1;
temp.start.y=y1;
temp.end.x=x2;
temp.end.y=y2;
floor_plan.lines.push_back(temp);
std::cout<<"LINE: :"<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<std::endl;
}
void
add_circle(double x, double y, double R)
{
// Yet to do
}
void
add_text(double x, double y, char *txt)
{
// Make something with that
}
int
load_dwg(char *filename)
{
unsigned int i;
int success;
Dwg_Data dwg;
dwg.num_objects = 0;
success = dwg_read_file(filename, &dwg);
for (i = 0; i < dwg.num_objects; i++)
{
Dwg_Entity_LINE *line;
Dwg_Entity_CIRCLE *circle;
Dwg_Entity_TEXT *text;
switch (dwg.object[i].type)
{
case DWG_TYPE_LINE:
line = dwg.object[i].tio.entity->tio.LINE;
add_line(line->start.x, line->end.x, line->start.y, line->end.y);
break;
case DWG_TYPE_CIRCLE:
circle = dwg.object[i].tio.entity->tio.CIRCLE;
add_circle(circle->center.x, circle->center.y, circle->radius);
break;
case DWG_TYPE_TEXT:
text = dwg.object[i].tio.entity->tio.TEXT;
add_text(text->insertion_pt.x, text->insertion_pt.y, (char*) text->text_value);
break;
}
}
dwg_free(&dwg);
return success;
}
What am I doing wrong? I believe libredwg is written in c. Is this the problem?
It seems that you are trying to link against a 32 bit library when you're on a 64 bit platform, like in this answer. Solution is to download (or build yourself from source) a 64 bit version of libredwg. Or alternatively add the "-m32" flag to your g++ command line - to build your whole app as a 32 bit executable.
EDIT : as you have found out, the problem is actually caused by trying to link C++ code with a C library without the following at the top / bottom of your code :
#ifdef __cplusplus
extern "C" {
#endif
// ... source code here
#ifdef __cplusplus
}
#endif
Basically this tells the compiler not to do C++ name-mangling - switching name mangling off allows linking between C and C++
Related
Edit: ***Sorry I realize there must have been some misunderstanding when posting this question, I want to specify that I DO realize this question was asked a few times, none of the answers work for me however***
I've been trying to link a simple static library test to one of my c++ projects, but I can't seem to get it quite right. I know that this is a very widespread topic and that a lot of people have already asked a similar question, but even after reading some of the answers, I still cannot, for the love of god, figure out what I am doing wrong.
My code is very simple, first I have a .cpp source file titled "Math.cpp" that looks like this:
#include "Math.h"
int max(int a, int b) {
return a > b ? a : b;
}
int min(int a, int b) {
return a < b ? a : b;
}
int floor(double a) {
return (int) a;
}
int ceil(double a) {
return (int) a + 1;
}
..And to go with that I made a header file called "Math.h" that looks like this:
#pragma once
int max(int, int);
int min(int, int);
int floor(double);
int ceil(double);
I then compile "Math.cpp" with the following command on cmd:
g++ -c Math.cpp -o Math.o
...and then compile it into a static library like so:
ar rcs libMath.a Math.o
After all of this I make a new c++ soure file titled "Main.cpp" that looks like this:
#include <iostream>
#include "Math.h"
int main() {
std::cout << max(9, 8) << std::endl;
return 0;
}
("Math.h" is in the same directory as "Main.cpp")
So finally in order to link "Main.cpp" with my static library ("libMath.a"), I use the following command in cmd:
g++ -o Main.exe Main.cpp -L. -lMath
however, at this point, it throws the following error:
C:\Users\zalmar\AppData\Local\Temp\ccmOnvyg.o:Main.cpp:(.text+0x18): undefined reference to `max(int, int)'
collect2.exe: error: ld returned 1 exit status
... I cannot figure out why it can't find the reference to the specific function. Some people appeared to have the same problem (here for example). Their solution was to declare the Main.cpp source file before declaring the library path. However, that was not the case for me, even though I made sure I was linking the library after the Main.cpp it still came up with the same error. I would greatly appreciate it if someone could point out anything I might be doing wrong because clearly I must be doing something wrong. Otherwise it might be a problem with my MinGW compiler, maybe?
I also want to re-mention that this is just a test library and I am fully aware that it might be a bit overkill to compile an entire static library from such a simple program. I am simply trying to figure out how to link libraries to my c++ projects...
I'm just getting started using nauty, which is written in C. Nauty comes with a program called geng that produces a file of graphs, but it's possible to call it from your own program, and work with the graphs one at a time. A sample C program is provided, and I'm trying to convert it to C++. The comments at the top of the program describe the general approach. I've listed both my program and geng.c, the source code from nauty, in my target.
Here's my code
/* This is a sample of how to call geng as a procedure rather than
* running it as a separate process. The basic idea is to construct
* an argument list for geng's main() function. At compile time,
* assign a name to the macros OUTPROC and GENG_MAIN. A typical
* Unix-style compilation command would be:
gcc -o callgeng -O3 -DMAXN=32 -DOUTPROC=myoutproc -DGENG_MAIN=geng_main \
callgeng.c geng.c nauty.a
*/
extern "C" {
#include "gtools.h"
}
static unsigned long counter;
extern "C" void
OUTPROC(FILE *outfile, graph *g, int n)
{
/* This will be called for each graph. */
++counter;
}
int GENG_MAIN(int geng_argc, char* geng_argv[]);
int
main(int argc, char *argv[])
{
int geng_argc;
char *geng_argv[6];
// Set up geng argument list. The 0-th argument is the command name.
// There must be a NULL at the end. This example is for trees
// of order 16.
char argv0[] = "geng";
char argv1[] = "-q";
char argv2[] = "-cbf";
char argv3[] = "16";
char argv4[] = "15";
geng_argv[0] = argv0;
geng_argv[1] = argv1;
geng_argv[2] = argv2;
geng_argv[3] = argv3;
geng_argv[4] = argv4;
geng_argv[5] = NULL;
geng_argc = 5;
counter = 0;
GENG_MAIN(geng_argc,geng_argv);
printf("Number of graphs = %lu.\n",counter);
return 0;
}
The program geng.c contains the lines:
#ifdef GENG_MAIN
int
GENG_MAIN(int argc, char *argv[])
#else
int
main(int argc, char *argv[])
#endif
When I try to build the project, it fails with a linker error:
Undefined symbols for architecture x86_64: "_geng_main", referenced
from:
_main in my_callgeng.o ld: symbol(s) not found for architecture x86_64
I tried compiling from the command line and it works fine.
>gcc -o callgeng -O3 -DMAXN=32 -DOUTPROC=myoutproc -DGENG_MAIN=geng_main -I/Users/saul/nauty26r7 my_callgeng.cpp ~/nauty26r7/geng.c ~/nauty26r7/nauty.a
>./callgen
Number of graphs = 19320.
So, it looks like an Xcode problem.
This was an Xcode error. I didn't realize that I had to put the compiler flags on each each line under BuildPhases/Compile Sources, so I only had "-DGENG_MAIN=geng_main" for my code, not for geng.c. Therefore the substitution didn't take place when geng.c was compiled, and it must have compiled _main, not _geng_main.
In your code (not geng.c), you need to add the extern "C" in front of
int
GENG_MAIN(int argc, char *argv[])
so that the compiler knows that this function (from geng.c) must use C linkage within your C++ instead of the default C++ linkage for that function (what you get when you don't specify in a file full of C++ code).
Basically, the C++ file uses C++ linkage for functions by default, and the C code uses C linkage for functions, so when you want the C code to be able to call something from the C++ code (your GENG_MAIN) you must specify in the C++ code that that particular function must be compiled with C linkage even though it is internally C++.
I created a static library that includes the follow C++ files:
//TestClass.h File:
#ifndef TESTCLASS_H_
#define TESTCLASS_H_
using namespace std;
#include <string>
class TestClass
{
public:
TestClass();
virtual ~TestClass();
int sum(int x, int y) const;
string chain(const string& x, const string& y) const;
};
#endif /* TESTCLASS_H_ */
//TestClass.cpp File:
#include<iostream>
#include "TestClass.h"
TestClass::TestClass()
{
}
TestClass::~TestClass()
{
}
int TestClass::sum(int x, int y) const
{
return x+y;
}
//Test.cpp File:
string TestClass::chain(const string& x, const string& y) const
{
return x+y;
}
int main(int argc, char* argv[])
{
TestClass test;
cout << "1+1 = " << test.sum(1,1) << endl;
cout << "Dog+Cat = " << test.chain("Dog","Cat") << endl;
return 0;
}
I added
-x objective-c++
flag in "Compile Source" and
-lstdc++
flag in "Info.plist Other Preprocessor flags".
When I link my just created static library (with Objective C wrapper files), I receive the 4 follow errors, that I don't have any idea how to fix it:
Undefined symbols for architecture arm64:
"vtable for __cxxabiv1::__class_type_info", referenced from:
typeinfo for TestClass in libPredictionComplete.a(TestClass.o)
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
"operator delete(void*)", referenced from:
TestClass::~TestClass() in libPredictionComplete.a(TestClass.o)
"___gxx_personality_v0", referenced from:
-[CppObject init] in libPredictionComplete.a(CppObject.o)
-[PredictionComplete init] in libPredictionComplete.a(PredictionComplete.o)
-[PredictionComplete chain::] in libPredictionComplete.a(PredictionComplete.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I'll appreciate any ideas about.
From my experience, Xcode will fail to link against C++ libraries when there are no C++ sources present in the top-level project. This is also true in pure Obj-C projects as well where you are linking against static libraries that have C++ code.
A less invasive solution is to simply include an empty C++ source file in your project (here's an example cpp stub) that is "compiled" into the final .app binary. It actually doesn't emit any code, but it makes Xcode aware that there is C++ code present, causing C++ libraries to be linked in.
The advantage of this solution is it avoids modifying the project settings in Xcode, so no need to add special linker flags to force Xcode to do the right thing.
I fixed it when I added the "-lstdc++" compile flag to "other linker flags" section in the Swift Project itself and not only in the static library project with c++ files.
The -lstdc++ should be in "Other Linker Flags" (or OTHER_LDFLAGS). Note that that will only work if the "C++ Standard Library" is set to libstdc++.
Also of note is that Xcode is usually smart enough to include the standard C++ library if the target has any C++ source code in it, so you don't need to explicitly link to either libstdc++ or libc++.
You should have -x c++ rather than objective-c++. There is, however, no need to specify this flag if you name your C++ sorce *.cpp.
I'm using a library that unfortunately, it appears the developer no longer works on or replies to issues in his Git repository. The library is used to drive HT1632C LED matrix drivers, and while it works in 0022/0023, it does not work in Arduino 1.0. When compiled, my Sketch gives the following error:
In file included from Final_code__1_0compatible.cpp:7:
C:\arduino-1.0\libraries\ht1632c/ht1632c.h:182: error: conflicting return type specified for 'virtual void ht1632c::write(uint8_t)'
C:\arduino-1.0\hardware\arduino\cores\arduino/Print.h:48: error: overriding 'virtual size_t Print::write(uint8_t)'
Referencing this site: http://arduino.cc/forum/index.php?topic=82450.0, I found a comment from someone who had the same compilation errors I did (but with another library). It looks like their fix was to replace something with "size_t"
Line 200: size_t write(uint8_t); //changed to resolve conflict with print.h
The conflicting lines in the library's .h and .cpp files look to be:
.h:
void write(uint8_t chr);
.cpp:
void ht1632c::write(uint8_t chr)
{
byte x, y;
if (chr == '\n') {
//y_cur += font_height;
} else {
//x_cur += putchar(x_cur, y_cur, chr, GREEN, PROPORTIONAL);
//x_cur = 0;
//y_cur = 0;
}
//sendframe();
}
I'm not a C/C++ expert, but am I correct, in that if I change the .h to be "size_t write(uint8_t chr)" and the .cpp to be "size_t ht1632c::write(uint8_t chr)" that this will work?
I tried doing it, and it compiles, but I don't know if I replace the word "void" with "size_t", or if I need to replace the "uint8_t" with "size_t".
so,
size_t ht1632c::write(uint8_t chr)
is the right function change. You should also add a
return 1;
right after the
sendframe();
line. write is expected to return the number of characters successfully written, as you don't have any way in the code as pasted to determine if there is an error in the writing, you should just say it worked.
I cannot figure out why this is not working. I will put up all three of my files and possibly someone can tell me why it is throwing this error. I am using g++ to compile the program.
Program:
#include <iostream>
#include "h8.h"
using namespace std;
int main()
{
char sentence[MAX_SENTENCE_LENGTH];
char writeTo[] = "output.txt";
int distanceTo,likePosition, length, numWords;
cout << "ENTER A SENTENCE! ";
cin.getline(sentence, 299);
length = strlen(sentence);
numWords = wordCount(sentence, length);
for(int x = 0; x < 3; ++x)
{
likePosition = likePos(numWords);
distanceTo = lengthTo(sentence, likePosition, length);
insertLike(sentence, distanceTo, length, writeTo);
}
return 0;
}
Function file:
void insertLike(const char sentence[], const int lengthTo, const int length, char writeTo[])
{
char part1[MAX_SENTENCE_LENGTH], part2[MAX_SENTENCE_LENGTH];
char like[] = " like ";
for(int y = 0; y < lengthTo; ++y)
part1[y] = sentence[y];
for(int z = lengthTo+1; z < length - lengthTo; ++z)
part2[z] = sentence[z];
strcat(part1, like);
strcat(part1, part2);
writeToFile(sentence, writeTo);
return;
}
Header file:
void insertLike(const char sentence[], const int lengthTo, const int length, const char writeTo[]);
The error exactly is:
undefined reference to 'insertLike(char const*, int, int, char const*)'
collect2: ld returned 1 exit status
The declaration and definition of insertLike are different
In your header file:
void insertLike(const char sentence[], const int lengthTo, const int length, const char writeTo[]);
In your 'function file':
void insertLike(const char sentence[], const int lengthTo, const int length,char writeTo[]);
C++ allows function overloading, where you can have multiple functions/methods with the same name, as long as they have different arguments. The argument types are part of the function's signature.
In this case, insertLike which takes const char* as its fourth parameter and insertLike which takes char * as its fourth parameter are different functions.
Though previous posters covered your particular error, you can get 'Undefined reference' linker errors when attempting to compile C code with g++, if you don't tell the compiler to use C linkage.
For example you should do this in your C header files:
extern "C" {
...
void myfunc(int param);
...
}
To make 'myfunc' available in C++ programs.
If you still also want to use this from C, wrap the extern "C" { and } in #ifdef __cplusplus preprocessor conditionals, like
#ifdef __cplusplus
extern "C" {
#endif
This way, the extern block will just be “skipped” when using a C compiler.
You need to compile and link all your source files together:
g++ main.c function_file.c
This could also happen if you are using CMake. If you have created a new class and you want to instantiate it, at the constructor call you will receive this error -even when the header and the cpp files are correct- if you have not modified CMakeLists.txt accordingly.
With CMake, every time you create a new class, before using it the header, the cpp files and any other compilable files (like Qt ui files) must be added to CMakeLists.txt and then re-run cmake . where CMakeLists.txt is stored.
For example, in this CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8.11)
project(yourProject)
file(GLOB ImageFeatureDetector_SRC *.h *.cpp)
### Add your new files here ###
add_executable(yourProject YourNewClass.h YourNewClass.cpp otherNewFile.ui})
target_link_libraries(imagefeaturedetector ${SomeLibs})
If you are using the command file(GLOB yourProject_SRC *.h *.cpp) then you just need to re-run cmake . without modifying CMakeLists.txt.
If you are including a library which depends on another library, then the order of inclusion is also important:
g++ -o MyApp MyMain.o -lMyLib1 -lMyLib2
In this case, it is okay if MyLib1 depends on MyLib2.
However, if there reverse is true, you will get undefined references.
As Paul said, this can be a linker complaint, rather than a compiler error. If you read your build output/logs carefully (may need to look in a separate IDE window to see the full details) you can dell if the problem is from the compiler (needs to be fixed in code) or from the linker (and need to be fixed in the make/cmake/project level to include a missing lib).