Thread: Use of C++ header file in C program file calling C++ function declared in that header

  1. #1
    Registered User
    Join Date
    Jul 2005
    Posts
    98

    Use of C++ header file in C program file calling C++ function declared in that header

    How to write a C++ header file that can be #included in a C source file when inheritance is used?
    I inherited a piece of software which uses both C and C++.
    A C++ header file "netlib_implementation.h" has:
    (s_libReceiveSocket and s_libSendSocket are "subclasses" of s_libSocket.)
    Code:
    typedef struct s_libSocket t_libSocket;
    struct s_libSocket {
      struct sockaddr sockAddr;
      int IP;
      int socketDescriptor;
    }
    typedef struct s_libReceiveSocket t_libReceiveSocket;
    struct s_libReceiveSocket : s_libSocket {
       pthread_mutex_t threadMutex;
       .... ;
    }
    typedef struct s_libSendSocket t_libSendSocket;
    struct s_libReceiveSocket : s_libSocket {
       pthread_cond_t cond;
       .... ;
    }
    A C++ program file "netlib.cc" has:
    Code:
    #include "netlib_implementation.h"
    typedef t_libSocket * netHandle;
    typedef t_libReceiveSocket * netRHandle;
    typedef t_libSendSocket * netSHandle;
    extern "C" netSHandle netOpenSendSocket( ... )
    {
      t_libSendSocket *s = malloc(...);
      ...
      return s;
    }
    extern "C" netRHandle netOpenSReceiveSocket( ... )
    {
      t_libReceiveSocket *s = malloc(...);
      ...
      return s;
    }
    A C program file "comm.c" calls the C++ functions:
    Code:
    #include "netlib.h"
    netHandle comm_handle;
    if (...)
      comm_handle = netOpenReceiveSocket( ... );
    else
      comm_handle = netOpenSendSocket( ... );
    Now the question is: How to write "netlib.h"?
    (Note that I cannot #include "netlib_implementation.h" in comm.c because "netlib_implementation.h" has some inheritance stuff in it and a C compiler does not recognize such.)
    Currently "netlib.h" is written as:
    Code:
    typedef void * netHandle;
    netHandle netOpenReceiveSocket( ... );
    netHandle netOpenSendSocket( ... );
    Note that the return type of the two function prototypes is netHandle, not netRHandle and netShandle as in the function definition. Also, there would be two different declarations of netHandle, one as void * in "netlib.h", another as t_libSocket * in "netlib.cc". That would be quite confusing.
    Is there a better way to handle this?

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by hzmonte
    How to write a C++ header file that can be #included in a C source file when inheritance is used?
    I inherited a piece of software which uses both C and C++.
    You don't. The second you add some C++ code, you're no longer programming in C, and you need a C++ compiler.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    C++ provides the 'extern "C"' facility so that a C++ function can be used by a C program. So there does not seem to be anything wrong calling C++ code in a C program. I am not talking about mixing C and C++ in one source file; I am talking about calling a C++ function (defined in a C++ source file) in a C source file.

    And how about this for "netlib.h":
    Code:
    #ifdef __cplusplus /* included in a C++ program */
    typedef t_libSocket * netHandle; /* function as forward decl */
    typedef t_libReceiveSocket * netRHandle; /* forward decl */
    typedef t_libSendSocket * netSHandle; /* forward decl */
    netRHandle netOpenReceiveSocket( ... );
    netSHandle netOpenSendSocket( ... );
    #else /* included in a C program */
    typedef t_libSocket * netHandle; /* function as forward decl */
    netHandle netOpenReceiveSocket( ... );
    netHandle netOpenSendSocket( ... );
    #endif
    And "netlib.cc" would become:
    Code:
    #include "netlib.h"
    #include "netlib_implementation.h"
    extern "C" netSHandle netOpenSendSocket( ... )
    {
      t_libSendSocket *s = malloc(...);
      ...
      return s;
    }
    extern "C" netRHandle netOpenSReceiveSocket( ... )
    {
      t_libReceiveSocket *s = malloc(...);
      ...
      return s;
    }

  4. #4
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    I am glad to report that my approach works , though I still do not know exactly why it works - specifically why C (specifically gcc 3.4.4 on Solaris 9) would accept a prototype
    baseType func(baseType);
    whereas the function definition in C++ is
    derivedType func(derivedType);
    I would appreciate it if someone could explain.
    Last edited by hzmonte; 06-16-2006 at 05:47 PM.

  5. #5
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by hzmonte
    C++ provides the 'extern "C"' facility so that a C++ function can be used by a C program. So there does not seem to be anything wrong calling C++ code in a C program. I am not talking about mixing C and C++ in one source file; I am talking about calling a C++ function (defined in a C++ source file) in a C source file.
    Actually it's the other way. Extern "C" tells a C++ compiler to compile that bit of code as C code.

    At least that's what my books sais.

    And It explains why all my compilers C headers are sorounded by extern "C"{}.
    Last edited by King Mir; 06-15-2006 at 11:29 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  6. #6
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    Quote Originally Posted by hzmonte
    C++ provides the 'extern "C"' facility so that a C++ function can be used by a C program.
    Quote Originally Posted by King Mir
    Actually it's the other way. Extern "C" tells a C++ compiler to compile that bit of code as C code.
    I think we are saying the same thing:
    1. C++ provides the 'extern "C" ' facility
    2. 'extern "C" ' tells the C++ compiler to compile that bit of code as C code
    3. Then that code, which is a C++ function itself, can be used by a C program
    The only thing I have some doubt is that, strictly speaking, the C++ compiler might not compile that piece of code as C code; it may compile it as some C++ code that is understandable by a C program. I am not sure about this. I know it has to do with some name mangling issue. But this is not important for my purpose.

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by hzmonte
    I think we are saying the same thing:
    1. C++ provides the 'extern "C" ' facility
    2. 'extern "C" ' tells the C++ compiler to compile that bit of code as C code
    3. Then that code, which is a C++ function itself, can be used by a C program
    1 - Yes.
    2 - Yes.
    3 - No. What do you think we're telling you here? NO YOU CANNOT USE C++ CODE IN A C PROGRAM ON A C COMPILER. You can use C code on a C++ compiler. You cannot use C++ code on a C compiler. For that matter, some C code will not compile on a C++ compiler without changes. In short, NO. You're wrong. It is a wrapper for your C code to work on a C++ compiler, not a wrapper so C++ code works on a C compiler.

    You have it backwards.

    Just because you look into a mirror and see your reflection, doesn't mean the people on the other side of the mirror see their reflection. They're really staring at you. Think about that.


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    Going back to my question s to why C (specifically gcc 3.4.4 on Solaris 9) would accept a prototype
    baseType func(baseType);
    whereas the function definition in C++ is
    derivedType func(derivedType);
    I did some more experiment and discovered that g++ would issue an error if I change the prototype for C++ as
    baseType func(baseType);
    That is, it is OK to say in a header file:
    Code:
    #ifdef __cplusplus /* for the use of a C program */
    extern "C"
    derivedType func(derivedType);
    #else  /* for the use of a C program */
    baseType func(baseType); 
    #endif
    but not OK to say
    Code:
    #ifdef __cplusplus /* for the use of a C program */
    extern "C"
    baseType func(baseType); 
    #else  /* for the use of a C program */
    baseType func(baseType); 
    #endif
    It is interesting that gcc would correctly (at least I did not see any run-time error) link to that C++ function even though the prototype it (i.e. the C compiler) sees does not exactly match to the function definition in the C++ program file.

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Read my text: Compiler specific. Not ANSI C. C does not support C++ code. Your compiler might, but that doesn't make it C.


    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    Quote Originally Posted by quzah
    NO YOU CANNOT USE C++ CODE IN A C PROGRAM ON A C COMPILER. You can use C code on a C++ compiler. You cannot use C++ code on a C compiler. For that matter, some C code will not compile on a C++ compiler without changes. In short, NO. You're wrong. It is a wrapper for your C code to work on a C++ compiler, not a wrapper so C++ code works on a C compiler.

    You have it backwards.
    Section 9.2.4 "Linkage to Non-C++ Code" of Stroustrup's "The C++ Programming Language, special edition" (2000) reads:
    Typically, a C++ program contains parts written in other languages. Similarly, it is common for C++ code fragments to be used as parts of programs written mainly in some other langauge.
    The way I read the second sentence is : "C++ code can be used as parts of a program written in some other langauge such as C. In other words, C++ code can be called from a C program." And of course, the implicit assumption is that this C program is to be compiled by a C compiler.
    My understanding of this paragraph, therefore, is that it is a two-way street. C++ program can call C code, and C program can call C++ code.
    My understanding of what you mean is that one can wrap an extern "C" around the declaration of a C function (which is compiled by a C compiler) and #include this declaration in a C++ program file and then compile this C++ program (with linkage to the C function) with a C++ compiler.
    What I am saying, and you disagree, is that one can also wrap a extern "C" around the declaration of a C++ function (which is compiled by a C++ compiler) and #include this declaration in a C program file and then compile this C program (with linkage to the C++ function) with a C compiler.
    Unfortunately, the examples in the rest of Sec 9.2.4 can be interpreted either way. Maybe Stroustrup means that it can be done either way, as I suggest.
    I have not seen anything in Stroustrap's book or other books that says C cannot call an extern-C-wrapped C++ function. On the other hand, Stroustrap does say "it is common for C++ code fragments to be used as parts of programs written mainly in some other langauge" (such as C). Can anyone show me where in the C++ Standard or any other books that say this is not allowed or this is not what it means?

    Quote Originally Posted by King Mir
    Extern "C" tells a C++ compiler to compile that bit of code as C code.
    To be exact, Stroustrap does not say the exern-C-wrapped C function (or an extern-C-wrapped C++ function, if that is allowed) is to be compiled as C code. He says the function "should be linked according to the C linkage convention." I am not familiar with compilation and linking, but I think there is a difference between teh two. He does not say how the code is compiled, he just say how it is linked.

  12. #12
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    I find it funny that you choose to believe your interpretation of a somewhat vague quotation from Bjarne Stroustrup over a direct statement that any C programmer would tell you, including Bjarne Stroustrup if you asked him directly.

    We are telling you this because we know it for a fact. YOU CAN NOT USE C++ CODE IN A STANDARD C PROGRAM.

    The way I take that quote is saying that in some large systems, it's not uncommon to see small bits of the application written in C++ because of it's speed advantages while the rest of the system is developed in another language. In fact, if you look in a lot of banking systems, you find most of the code is still in COBOL while some of the modern processes are passed to things written in C or C++. It's not compiled or linked together in anyway, they just simply interact with each other. Just as a system's kernel will interact with other applications. I don't know if this is what he meant either, but one could interpret that is what he meant.
    Last edited by SlyMaelstrom; 06-16-2006 at 07:16 PM.
    Sent from my iPadŽ

  13. #13
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Well I suppose it might be possible to compile main() as a C function, while other functions would use C++. You would still need a C++ compiler to compile C++ regardless. And extern "C" would still mark the functions that are compiled as C code, not C++ code.

    Furthermore you could compile a C++ library into assembly code and include that in your C code.

    The convention is to use C code inside C++, not the other way around. After all, what's the point?
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  14. #14
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by King Mir
    Well I suppose it might be possible to compile main() as a C function, while other functions would use C++. You would still need a C++ compiler to compile C++ regardless. And extern "C" would still mark the functions that are compiled as C code, not C++ code.
    http://www.parashift.com/c++-faq-lit....html#faq-32.1
    You must use your C++ compiler when compiling main() (e.g., for static initialization)
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  15. #15
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by Dave_Sinkula
    Here's a question then: If since a call to main() is valid in C, but not C++, would it be possible to call main() from a C function included in a C++ project?
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding Header Files
    By Kaidao in forum C++ Programming
    Replies: 11
    Last Post: 03-25-2008, 10:02 AM
  2. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  3. Calling a Thread with a Function Pointer.
    By ScrollMaster in forum Windows Programming
    Replies: 6
    Last Post: 06-10-2006, 08:56 AM
  4. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  5. Possible circular definition with singleton objects
    By techrolla in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2004, 10:46 AM