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

Hybrid View

Previous Post Previous Post   Next Post Next Post
  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
    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.

  5. #5
    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.

  6. #6
    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.*

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

  8. #8
    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.

  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
    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Ž

  12. #12
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    SlyMaelstrom and quzah, can you take a deep breath and allow the possibility that you and a handful of other C/C++ programmers are wrong on this? As a scientist, I do not just take other people's words for it. Besides, you are not Stroustrup, no offense. I have taken the time to search the literature and test the code, why don't you do the same and prove me wrong? You guys keep saying "YOU CAN NOT USE C++ CODE IN A STANDARD C PROGRAM." Basically what you are saying is just "Trust me, it cannot be done, it is wrong." It is not that I do not want to trust you, it is just that it is not a very scientiific way of seeking knowledge.
    Quote Originally Posted by quzah
    "Some other language" doesn't mean C. It doesn't say C, you assumed it.
    I did not assume it. I said "such as C". It surely does not say C; but it can be C, can't it? And the entire section 9.2.4 talks about the interaction between C and C++. I believe that C is a very reasonable candidate for such a "some other langauage". Why don't you tell me what this "some other langauge" refers to if you think C is not such one? And what makes you think C is not such one? Getting emotional and citing what "everybody else is telling [me] otherwise" is not the way to convince people.
    Quote Originally Posted by quzah
    Pull your head out of your ass and listen. ... Frankly at this point I don't give a ........ if you ever learn anything.
    That kind of attitude only makes me place less trust and attention on what you say. But I do hope that you will learn how to engage in a civilized and productive discussion. The entire section 9.2.4 talks about the interaction of C and C++ but all you keep saying is simply "it isn't C" without explaining why you think it cannot be C, and then you expect others to just trust you because you say so.

  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