I have been recently practicing managing multiple objects and drawing them in C++ using SFML library. I wanted my textures and future resources to be more reusable so I decided to make use of Thor library which suits my needs really well.
So I've written first few lines of code based on what you can find in this tutorial and the compiler always says:
main.cpp|12|error: 'textures_holder' does not name a type
This line gives an error :
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
I'm using Code::Blocks IDE with MinGW compiler and SFML 2.5.0.
Here's my main.cpp and the header file which contains extern object :
//...
#include <Thor/Resources.hpp>
#include "Dirt_Block.h"
using namespace std;
//Adding textures to the texture library
//THIS LINE GIVES AN ERROR
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
//Rest of code...
Dirt_Block.h (only the upper part) :
#ifndef DIRT_BLOCK_H
#define DIRT_BLOCK_H
#include <SFML\Graphics.hpp>
#include <vector>
#include <Thor/Resources.hpp>
#include <Thor/Resources/SfmlLoaders.hpp>
extern sf::Vector2u screenRes;
extern thor::ResourceHolder<sf::Texture, std::string> textures_holder;
//Rest of the code
I'd like to know what is causing this error and maybe help others who may experience similiar frustrating problems. Thanks for help.
EDIT :
As suggested in the comment I've declared a few extern int variables in the Dirt_Block.h so now it looks like this :
//...
extern int test_int_up;
extern sf::Vector2u screenRes;
extern thor::ResourceHolder<sf::Texture, std::string> textures_holder;
extern int test_int_d;
//...
And then assinged to them some value in main.cpp :
//...
test_int_up = 55;
test_int_d = 55;
//Adding textures to the texture library
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
//...
But the compiler gives error :
main.cpp|9|error: 'test_int_up' does not name a type
main.cpp|10|error: 'test_int_d' does not name a type
main.cpp|12|error: 'textures_holder' does not name a type
Much less distracting to see what your problem is without all the extraneous code!
C++ programs don't start from the top of the file and run code down to the bottom. They start at the main(), and control flow proceeds from there, with one thing triggering another.
(Note: That doesn't take into account global constructor ordering, which does go in order of declaration--but you have no guarantee of the order declarations from "different files" might run in.)
Point being, you can't just make random function or method calls in the middle of a file. That's where you put declarations. You have to be inside of a function or method to make calls, e.g.
int main() {
textures_holder.acquire(
"Dirt",
thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png")
);
...
}
I am working on a school project which requires to work with sheepdog. Sheepdog provides a c api which enables you to connect to a sheepdog server.
First i create c source file(test.c) with the following content :
#include "sheepdog/sheepdog.h"
#include <stdio.h>
int main()
{
struct sd_cluster *c = sd_connect("192.168.1.104:7000");
if (!c) {
fprintf(stderr, "failed to connect %m\n");
return -1;
}else{
fprintf(stderr, "connected successfully %m\n");
}
return 0;
}
then i compile with no error using the following command
gcc -o test test.c -lsheepdog -lpthread
But what i need is to use it with c++ project so i created a cpp file(test.cpp) with the following content :
extern "C"{
#include "sheepdog/sheepdog.h"
}
#include <stdio.h>
int main()
{
struct sd_cluster *c = sd_connect("192.168.1.104:7000");
if (!c) {
fprintf(stderr, "failed to connect %m\n");
return -1;
}else{
fprintf(stderr, "connected successfully %m\n");
}
return 0;
}
now, when i compiled using the following command :
g++ -o test test.cpp -lsheepdog -lpthread
I got this error :
You can't just wrap extern "C" around a header and expect it to compile in a C++ program. For example, the header sheepdog_proto.h uses an argument named new; that's a keyword in C++, so there's no way that will compile as C++. The library was not designed to be called from C++.
I agree with #PeteBecker. From a quick look around Google, I am not sure there is an easy solution. Sheepdog is using C features and names that don't port well to C++. You might need to hack sheepdog fairly extensively. For example:
move the inline functions out of sheepdog_proto.h into a new C file, leaving prototypes in their place. This should take care of the offsetof errors, e.g., discussed in this answer.
#define new not_a_keyword_new in sheepdog/sheepdog.h
and whatever other specific changes you have to make to get it to compile. More advice from the experts here.
As sheepdog was not designed to be useable from C++ you should build a tiny wrapper in C language to call the functions from sheepdog and only call the wrapper from your c++ code. Some hints to write such a wrapper:
void * is great to pass opaque pointers
extractors can help to access badly named members. If a struct has a member called new (of type T), you could write:
T getNew(void *otherstruct); // declaration in .h
and
T getNew(void *otherstruct) { // implementation in a c file
return ((ActualStruct *) otherstruct)->new;
}
Depending on the complexity of sheepdog (I do not know it) and the part you want to use, it may or not be an acceptable solution. But it is the way I would try facing such a problem.
Anyway, the linker allows mixing modules compiled in C and in C++, either in static linking or dynamic linking.
I am not familiar with link errors at all so I was hoping someone could shed some light on these errors...
I am working with a Legacy Ada program. I am developing a C++ Extension in which the Ada will use a proxy to call the C++ functions. The C++ compiles cleanly without any warnings. However I am getting the following Undefined Symbol errors:
__nw__FUi
__walkback
__dl__FPv
The code base is as follows:
#include "cppProxy.h"
extern classHandler *classPtr;
void processData(void* ioBuffer)
{
classPtr->processData(ioBuffer);
}
Header File:
#include "classHandler.h"
extern "C" void processData(void* ioBuffer);
classHandler.cpp
extern "C"
{
classHandler* create()
{
return new classHandler;
}
void destroy(classHandler *p)
{
delete p;
}
}
void processData(*ioBuffer)
{
int idx;
data = static_cast<int*>(ioBuffer);
idx = (data[0] >> 16);
returnData[idx] = data;
}
classHandler.h
class classHandler
{
public:
classHandler();
~classHandler();
void processData(void* ioBuffer);
};
typedef classHandler classPtr;
typedef void destroy_t(classHandler*);
Now the objective is to have the C++ keep track of the object so I was trying to create a singleton that would then be called. Looking at the current state of the code I am trying to figure out where this is since I have done multiple changes trying to fix the linker error.
Overall I am wondering if this is truly a linking error or an issue with my class implementation. I am leaning towards the latter but still uncertain on how to resolve the issue.
Once again the design I am going for is as follows:
Implemented:
Ada calls the C++ to process data.
C++ parses the data and stores it locally.
Not Implemented:
Ada calls the C++ to retrieve the data.
C++ does a lookup and returns data array.
Any help would be appreciated on this since I am lost in my own code at the moment. Thanks!
EDIT1:
The Ada code is too robust but I know with certainty that that side is correct. As for the compiler, I am using Concurrent ANSI C/C++ compiler (PowerPC) – 5.4 (005). I CANNOT change compilers. The first two fragments are the proxy layer of the code. This is what the Ada portion uses to interface into the C++ code.
I have the following c++ program:
Client.h
#ifndef Client_Client_h
#define Client_Client_h
#include "Client.h"
class Client {
public:
void f1();
void f2();
};
#endif
Client.cpp
#include <iostream>
#include <stdlib.h>
using namespace std;
#include "Client.h"
void Client::f1(){
cout << "Client.f1()" << endl;
}
void Client::f2() {
cout << "Client.f2()" << endl;
}
compiling the above in XCode 4.3 gives me a static library file called:
libClient.a
Separately, I have a main.c
#include <stdio.h>
//
//using namespace std;
int main(){
// how do I do something like: Client c; c.f1(); c.f2();
// and actually get output ?
printf("hello\n");
return 0;
}
What's steps do I need to take in order to invoke f1() and f2() ? How do I use GCC to link the static library properly?
So far I have tried:
gcc -lClient.a main.c
which gives me :
ld: library not found for -lClient.a
collect2: ld returned 1 exit status
This isn't going to work, or at least is not going to be portable. The one really really obvious thing to do is to make your program C++ so you can access those features.
You can't "natively" use C++ code from C code, for obvious reasons. You don't have access to object-oriented features, so a ton of stuff isn't going to work: constructors, destructors, move/copy semantics and virtual inheritance are probably the biggest things that you'll miss. (That's right: you won't be able to create or destroy objects correctly, unless they have trivial constructors and destructors.)
You'll also run into linkage issues: C++ function names are mangled into a mess that includes their parameter types and return types and classes, which will look like __1cGstrcpy6Fpcpkc_0_. It would be technically feasible to declare the mangled names of the functions in C to use them, or use dlsym to get a pointer to them, but that's plain silly. Don't do that.
If you need to create a function in C++ that needs to be callable from C, you can specify it as extern "C" and its name won't be mangled, and it will be accessible from C, and it will be itself able to use C++ features:
extern "C" void Foo()
{
std::string hello = "Hello world!";
std::cout << hello << std::endl;
}
You will then need to declare it on the C side of your program like this:
void Foo();
And you'll be able to call it.
It's possible for you to wrap all your C++ calls that you want to expose to your C program in extern "C" functions, and return a pointer to your type and deal with it that way, but it's going to get annoying very quickly. You really should just use C++.
As far as linking with the static library is concerned, in Xcode, go to your project settings, pick your target, go to the Build Phases tab, unfold the "Link Binary With Libraries" section, and drop your .a file there.
I am wondering if there is some way to call C++ code from Common Lisp (preferably portably, and if not, preferably in SBCL, and if not, well, then Clozure, CLisp or ECL).
The C++ would be called inside loops for numeric computation, so it would be nice if calls were fast.
CFFI seems to not support this:
"The concept can be generalized to
other languages; at the time of
writing, only CFFI's C support is
fairly complete, but C++ support is
being worked on."
(chapter 4 of the manual)
SBCL's manual doesn't mention C++ either; it actually says
This chapter describes SBCL's
interface to C programs and libraries
(and, since C interfaces are a sort of
lingua franca of the Unix world, to other programs and libraries in
general.)
The C++ code uses OO and operator overloading, so it really needs to be compiled with g++.
And as far as I know, I can have a C++ main() function and write wrappers for C functions, but not the other way around -- is that true?
Anyway... Is there some way to do this?
Thank you!
After compiling, most C++ functions actually boil down to regular C function calls. Due to function overloading and other features, C++ compilers use name mangling to distinguish between similarly named functions. Given an object dump utility and sufficient knowledge about your C++ compiler, you can call C++ code directly from the outside world.
Having said that though, you may find it easier to write a C-compatible layer between Lisp and your C++ code. You would do that using extern "C" like this:
extern "C" Foo *new_Foo(int x)
{
return new Foo(x);
}
This makes the new_Foo() function follow the C calling convention so that you can call it from external sources.
The main difference in calling C++ functions instead of C functions apart from the name mangling are the 'hidden' features like this pointers that are implicitly passed to member functions. The C runtime layer doesn't know anything about these, implicit type conversions and other fun C++ features, so if you intend to call C++ through a C interface, you might have to fake these features if necessary.
Assuming that you can hold at least a void * to the object you intend to call and the data it requires, you can degrade the following C++ call
matrix->multiply(avector);
to a C call if you create a C wrapper function:
extern "C"
void matrix_multiply(void *cpp_matrix, void *cpp_vector) {
reinterpret_cast<matrix_type *>(cpp_matrix)->multiply(reinterpret_cast<vector_type *>(cpp_vector);
}
Obviously the function matrix_multiply would sit in the C++ source code and compiled as such but it does expose a C interface to the outside world. As long as you can interact with the opaque pointers, you're OK with the translation shims above.
Admittedly this is not necessarily the most elegant solution for a problem like this but I've used it in the past in situations like yours.
The other option would be to make the C++ calls directly by treating them as C calls with additional parameters and supplying all the required information yourself, but that does move you into the realm of compiler-specific code very quickly. Basically, you would still be holding the opaque pointers to C++ objects, but you'd have to work out the mangled name of the function you want to call. Once you've got that function name, you'll have to supply the this pointer (which is implicit in C++ and semi-implicit in the example above) and the correct parameters and then call the function. It can be done but as mentioned, puts you deeply in to the realm of compiler and even compiler-version specific behaviour.
Oh, wait!
It seems that there is a trick I can use!
I write a wrapper in C++, declaring wrapper functions extern "C":
#include "lib.h"
extern "C" int lib_operate (int i, double *x) {
...
}
The header file lib.h, which can be called from both C and C++, is:
#if __cplusplus
extern "C" {
#endif
int lib_operate (int i, double *x);
#if __cplusplus
}
#endif
Then compile with:
g++ -c lib.cpp
gcc -c prog.c
gcc lib.o prog.o -lstdc++ -o prog
Seems to work for a toy example! :-)
So, in Common Lisp I'd call the wrapper after loading libstdc++.
Anyway, thank you for your answers!
Update 2021:CL-CXX-JIT which handles most of the work on the lisp side.
Example:
(ql:quickload :cxx-jit)
(in-package cxx-jit)
(from '("<cmath>") 'import '("static_cast<double(*)(double)>(std::sin)" . "cpp-sin"))
(cpp-sin 0d0)
(from nil 'import "struct C{ auto hi(){return \"Hello, World\\n\";} auto bye(){return \"Bye\";} };" '("&C::bye" . "bye") '("&C::hi" . "hi") '("[](){static C x; return x;}" . "cc"))
(cc)
(hi *)
(bye **)
You can use cl-cxx which is like writing pybind11 for python.
example in c++ 'std >= c++14', compiled as shared lib:
#include <string>
#include "clcxx/clcxx.hpp"
class xx {
public:
xx(int xx, int yy) : y(yy), x(xx) {}
std::string greet() { return "Hello, World"; }
int y;
int x;
};
std::string greet() { return "Hello, World"; }
int Int(int x) { return x + 100; }
float Float(float y) { return y + 100.34; }
auto gr(std::complex<float> x) { return x; }
std::string hi(char* s) { return std::string("hi, " + std::string(s)); }
void ref_class(xx& x) { x.y = 1000000; }
CLCXX_PACKAGE TEST(clcxx::Package& pack) {
pack.defun("hi", F_PTR(&hi));
pack.defun("test-int", F_PTR(&Int));
pack.defun("greet", F_PTR(&greet));
pack.defun("test-float", F_PTR(&Float));
pack.defun("test-complex", F_PTR(&gr));
pack.defun("ref-class", F_PTR(&ref_class));
pack.defclass<xx, false>("xx")
.member("y", &xx::y)
.defmethod("greet-from-class", F_PTR(&xx::greet))
.constructor<int, int>();
}
usage in lisp:
(cffi:use-foreign-library my-lib)
(cxx:init)
(cxx:add-package "TEST" "TEST")
(test:greet)
(setf my-class (test:create-xx2 10 20))
(test:y.get myclass)
That would take care of all conversions, extern "C", ... for you.
Depending on your C++ ABI, your wrapper (lib_operate above) might need to somehow handle any C++ exceptions that might occur. If your ABI does table-drive exception handling, unhandled exceptions will simply crash the (Lisp) process. If it instead does dynamic registration, you might not even notice that anything went wrong. Either way, it's bad.
Or, if you've got the no-throw guarantee for the wrapped code, you can ignore all this.