4

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 : compilation error message

5
  • Try with g++ -o test test.cpp -L/Absolut/PATH/TO/sheepdog -lpthread Commented Aug 19, 2016 at 14:28
  • @Phiber having the same problem Commented Aug 19, 2016 at 14:41
  • Just for grins, did you try it without the extern "C" first? Is this file the sheepdog/sheepdog.h? (I don't see a sheepdog/sheepdog.h under include/ in GitHub.) Commented Aug 19, 2016 at 14:49
  • it seems also you have problem with include headers, try with: g++ -I /sheepdog/headers OR set CPLUS_INCLUDE_PATH env variable Commented Aug 19, 2016 at 14:52
  • @cxw yes i tried and the same error happened Commented Aug 19, 2016 at 15:14

3 Answers 3

6

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++.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

5 Comments

@PeteBecker if i create .so library in c using this library which provide me the functions that i need in my c++ program then link it with my c++ program .will this work
#define new ... produces undefined behavior.
@PeteBecker in this situation? For sheepdog, I would think new would just be an identifier susceptible to redefinition like any other identifier. Sheepdog has no calls to operator new, so the compiler wouldn't have a reason to treat something called foo_new specially. Am I missing something? --- I also found this answer to a vaguely-related question :) .
@cxw - redefining any C++ keyword with a macro produces undefined behavior. It might be that that turns out to be harmless, but that doesn't change what it is.
For future readers of this post - more about #define new and friends
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.