Thread: Calling C++ function from C (yes I realise this has been done to death !)

  1. #1
    Registered User
    Join Date
    Apr 2012
    Posts
    16

    Calling C++ function from C (yes I realise this has been done to death !)

    I have my GatewayLT.hpp list class:

    Code:
    class GatewayList
    {
    private:
        typedef std::list<Gateway*> GatewayStoreType;
        GatewayStoreType store;
    
    public:
        void AddGateway(Gateway * const gw);
        void Send(struct lgw_pkt_rx_s pkt_data);
    };
    
    
    extern "C" void call_GatewayList_Send(struct lgw_pkt_rx_s pkt_data)
    {
        Global::gatewayList.Send(pkt_data);
        return;
    }
    This list resides in my GlobalDataLT.hpp class as below:
    Code:
    namespace Global
    {
        //below defined in GlobalDataLT.cpp
        extern GatewayList gatewayList;
    }
    I want to call Global::gatewayList.Send(...).
    1. Including the GlobalDataLT.hpp file in my C code and calling Global::gatewayList.Send() yields 100s of errors
    2. Using the extern function call_GatewayList_Send as defined in my GatewayLT.hpp (as you can see above) seems to be the recommended way but when compiling the C file I still get an error:
    Code:
    sx1272.c:1982: undefined reference to `call_GatewayList_Send'
    although it's definitley in the GatewayLT.hpp as you can see and I've defined the prototype for it in my .c file.
    So what's the correct way to get around this ?

    regards

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Have you put the prototype in the C file?
    Code:
    void call_GatewayList_Send(struct lgw_pkt_rx_s pkt_data);
    The C file will also need the definition of the struct.

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    You may want to read the following link: How to Mix C and C++.

    Also I'd recommend against having the function implementation inside a header file when trying to mix these two languages.

    Next I'd recommend trying to use non class member functions whenever possible. For example GatewayList.send() looks like it could be a non-class function since it doesn't appear to be using any class member variables.

    Lastly when possible you should really consider using the C++ compiler to compile the program, rather than the C compiler.


    Jim

  4. #4
    Registered User
    Join Date
    Apr 2012
    Posts
    16
    Quote Originally Posted by algorism View Post
    Have you put the prototype in the C file?
    Code:
    void call_GatewayList_Send(struct lgw_pkt_rx_s pkt_data);
    The C file will also need the definition of the struct.
    yes the prototype is definitely in the C file as I said above, but in any case here is the direct cut from the file:

    Code:
    void call_GatewayList_Send(struct lgw_pkt_rx_s pkt_data);
    void MGWIfaceSendToGateways()
    {
    ....
        call_GatewayList_Send(pkt_data);
    }

  5. #5
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    How are you compiling it? Are you including the C++ object file (containing call_GatewayList_Send)?
    Code:
    // File: a.hpp
    #ifndef CLASS_A_
    #define CLASS_A_
    
    class A {
    private:
        int n;
    public:
        A(int n=123) : n(n) {}
        int getn() {return n;}
    };
    #endif
    
    
    // File: a.cpp
    #include "a.hpp"
    
    namespace Global {
        A a;
    }
    
    extern "C" int func() {
        return Global::a.getn();
    }
    
    
    // File x.c
    #include <stdio.h>
    
    int func();
    
    int main(void) {
        printf("%d\n", func());
        return 0;
    }
    
    // To compile:
    //  g++ -c a.cpp
    //  gcc x.c a.o
    Last edited by algorism; 10-11-2016 at 08:59 AM.

  6. #6
    Registered User
    Join Date
    Apr 2012
    Posts
    16
    Thanks for that, what you have said is pretty much what I have done now. Worth pointing out I'm building in the Eclipse IDE environment with a Cygwin compiler. The code is pretty much 50% C and 50% C++.
    Still get the annoying error
    undefined reference to `call_GatewayList_Send'
    and I do have the prototype for it in the .c file.
    I'll sleep on it and see if I come up with something in the morning,

  7. #7
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    That sounds like a linker error (as opposed to a compiler error). So you're probably not compiling it correctly.

  8. #8
    Registered User
    Join Date
    Apr 2012
    Posts
    16
    Quote Originally Posted by algorism View Post
    That sounds like a linker error (as opposed to a compiler error). So you're probably not compiling it correctly.
    Turns out I needed the following around my extern "C":
    Code:
    #ifdef __cplusplus
    extern "C" void call_GatewayList_Send(struct lgw_pkt_rx_s pkt_data);
    #endif
    then define the function in the cpp file as such:
    Code:
    void call_GatewayList_Send(struct lgw_pkt_rx_s pkt_data)
    {
        Global::gatewayList.Send(pkt_data);
        return;
    }
    then add the prototype (wiithout the #ifdef __cplusplus and without extern "C" bit) to the .c file eg
    Code:
    void call_GatewayList_Send(struct lgw_pkt_rx_s pkt_data);
    and simply call it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 06-10-2013, 04:03 PM
  2. Replies: 3
    Last Post: 10-23-2012, 02:37 PM
  3. Replies: 15
    Last Post: 06-09-2009, 02:19 AM
  4. Calling Cdocument function in Cview function
    By RancidWannaRiot in forum Windows Programming
    Replies: 5
    Last Post: 09-22-2005, 12:09 PM
  5. Question on function syntax and calling function
    By cbrman in forum C Programming
    Replies: 10
    Last Post: 10-05-2003, 05:32 PM

Tags for this Thread