Question about C/C++ struct memory layout compatibility

Discussion in 'C++' started by Vincezo Ciaschini, Jun 9, 2005.

  1. Supposing you have the following declaration in a header file:
    -- head.h --

    struct s {
    int c;
    char v;
    #if defined(__cplusplus)
    s();
    s(double);
    method1(int);
    method2(float);
    #endif
    };

    and then two sources,

    -- cppsrc.cc --
    #include "head.h"

    extern "C" {
    s *create(void)
    {
    s *res = new s(1.0);
    res->method1(4);
    return res;
    }

    -- csrc.c --
    #include "head.h"

    extern struct s *create(void);

    int f()
    {
    struct s* val = create();
    val->v = 'd';
    }

    Is this legal/portable?

    Thanks in advance,
    Vincenzo
    Vincezo Ciaschini, Jun 9, 2005
    #1
    1. Advertising

  2. Vincezo Ciaschini wrote:
    > Supposing you have the following declaration in a header file:
    > -- head.h --
    >
    > struct s {
    > int c;
    > char v;
    > #if defined(__cplusplus)
    > s();
    > s(double);
    > method1(int);
    > method2(float);
    > #endif
    > };
    >
    > and then two sources,
    >
    > -- cppsrc.cc --
    > #include "head.h"
    >
    > extern "C" {
    > s *create(void)
    > {
    > s *res = new s(1.0);
    > res->method1(4);
    > return res;
    > }
    >
    > -- csrc.c --
    > #include "head.h"
    >
    > extern struct s *create(void);
    >
    > int f()
    > {
    > struct s* val = create();
    > val->v = 'd';
    > }
    >
    > Is this legal/portable?


    I have no definite answer to this question. I believe, though, that
    it would be implementation-specific. However, regardless of what I
    believe, I'd like to know *why* would you want to do something like
    that. Why do you feel the need to have both C and C++ translation units
    in the same program?

    V
    Victor Bazarov, Jun 9, 2005
    #2
    1. Advertising

  3. Vincezo Ciaschini

    Shezan Baig Guest

    Vincezo Ciaschini wrote:
    > Supposing you have the following declaration in a header file:
    > -- head.h --
    >
    > struct s {
    > int c;
    > char v;
    > #if defined(__cplusplus)
    > s();
    > s(double);
    > method1(int);
    > method2(float);
    > #endif
    > };
    >
    > and then two sources,
    >
    > -- cppsrc.cc --
    > #include "head.h"
    >
    > extern "C" {
    > s *create(void)
    > {
    > s *res = new s(1.0);
    > res->method1(4);
    > return res;
    > }
    >
    > -- csrc.c --
    > #include "head.h"
    >
    > extern struct s *create(void);
    >
    > int f()
    > {
    > struct s* val = create();
    > val->v = 'd';
    > }
    >
    > Is this legal/portable?



    I don't think so. I believe it violates the One Definition Rule. But
    I'm not sure if this applies when mixing C and C++.

    -shez-
    Shezan Baig, Jun 9, 2005
    #3
  4. Victor Bazarov wrote:

    > Vincezo Ciaschini wrote:
    >
    >> Supposing you have the following declaration in a header file:
    >> -- head.h --
    >>
    >> struct s {
    >> int c;
    >> char v;
    >> #if defined(__cplusplus)
    >> s();
    >> s(double);
    >> method1(int);
    >> method2(float);
    >> #endif
    >> };
    >>
    >> and then two sources,
    >>
    >> -- cppsrc.cc --
    >> #include "head.h"
    >>
    >> extern "C" {
    >> s *create(void)
    >> {
    >> s *res = new s(1.0);
    >> res->method1(4);
    >> return res;
    >> }
    >>
    >> -- csrc.c --
    >> #include "head.h"
    >>
    >> extern struct s *create(void);
    >>
    >> int f()
    >> {
    >> struct s* val = create();
    >> val->v = 'd';
    >> }
    >>
    >> Is this legal/portable?

    >
    >
    > I have no definite answer to this question. I believe, though, that
    > it would be implementation-specific. However, regardless of what I
    > believe, I'd like to know *why* would you want to do something like
    > that. Why do you feel the need to have both C and C++ translation units
    > in the same program?

    Because they would not be in the same program. The cppsrc.cc would be
    in a dynamic library that will be linked to the program containing
    csrc.c. It is an effort to provide a C interface to a C++ library.

    Bye,
    Vincenzo

    >
    > V
    Vincezo Ciaschini, Jun 9, 2005
    #4
  5. Shezan Baig wrote:

    > Vincezo Ciaschini wrote:
    >
    >>Supposing you have the following declaration in a header file:
    >>-- head.h --
    >>
    >>struct s {
    >> int c;
    >> char v;
    >>#if defined(__cplusplus)
    >> s();
    >> s(double);
    >> method1(int);
    >> method2(float);
    >>#endif
    >>};
    >>
    >>and then two sources,
    >>
    >>-- cppsrc.cc --
    >>#include "head.h"
    >>
    >>extern "C" {
    >>s *create(void)
    >>{
    >> s *res = new s(1.0);
    >> res->method1(4);
    >> return res;
    >>}
    >>
    >>-- csrc.c --
    >>#include "head.h"
    >>
    >>extern struct s *create(void);
    >>
    >>int f()
    >>{
    >> struct s* val = create();
    >> val->v = 'd';
    >>}
    >>
    >>Is this legal/portable?

    >
    >
    >
    > I don't think so. I believe it violates the One Definition Rule. But
    > I'm not sure if this applies when mixing C and C++.

    My doubt exactly, especially considering that the two definition are
    identical with respect to the included data.

    It seems reasonable to me that, if the data definition part is
    identical, and there is no virtual/RTTI on the C++ part, that the memory
    layout should be identical. However, I am not certain about this.

    Also, the cppsrc.cc code will be in a library linked by the csrc.c (and
    a main() function) code.

    Bye,
    Vincenzo

    >
    > -shez-
    >
    Vincezo Ciaschini, Jun 9, 2005
    #5
  6. Vincezo Ciaschini

    Shezan Baig Guest

    Vincezo Ciaschini wrote:
    > Because they would not be in the same program. The cppsrc.cc would be
    > in a dynamic library that will be linked to the program containing
    > csrc.c. It is an effort to provide a C interface to a C++ library.
    >




    You probably need to make a clean-cut between the C++ interface and the
    C interface, instead of attempting to mix them both in a single header
    file. Use 2 header files:

    head.h
    ------
    normal C++ declaration here

    head_c.h
    --------
    C declarations here

    hth,
    -shez-
    Shezan Baig, Jun 9, 2005
    #6
  7. Vincezo Ciaschini wrote:
    > Victor Bazarov wrote:
    > [...] I'd like to know *why* would you want to do something like
    >> that. Why do you feel the need to have both C and C++ translation units
    >> in the same program?

    >
    > Because they would not be in the same program. The cppsrc.cc would be
    > in a dynamic library that will be linked to the program containing
    > csrc.c.


    Read your own statement again. If it is _linked_, it's in the same
    program. By definition.

    > It is an effort to provide a C interface to a C++ library.


    I don't see any need to have a C struct created in C++ code and returned
    by a C function. It would be best to de-couple them altogether and use
    some kind of "handle" to identify your C++ object inside your C++ space.
    Your library is the only thing that should know about the inner workings
    of that object. The outside world should use the C interface to do all
    the processing. Passing the "handle" back and forth is the only answer
    AFAIK.

    <offtopic> But is it really needed to have C interface? How many
    customers do you have that use C versus C++ bindings? Any at all?
    Never mind. Marketing decisions are not necessarily based on common
    sense. And don't tell me that having a C interface is not a marketing
    decision.
    </offtopic>

    V
    Victor Bazarov, Jun 9, 2005
    #7
  8. Vincezo Ciaschini wrote:

    > It seems reasonable to me that, if the data definition part is
    > identical, and there is no virtual/RTTI on the C++ part, that the memory
    > layout should be identical. However, I am not certain about this.


    I think is unreasonable to worry about that. Just write a class that derives
    from or contains the C style struct and use it from C++.

    --
    Salu2
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Jun 9, 2005
    #8
  9. Vincezo Ciaschini

    Shezan Baig Guest

    Victor Bazarov wrote:
    > <offtopic> But is it really needed to have C interface? How many
    > customers do you have that use C versus C++ bindings? Any at all?
    > Never mind. Marketing decisions are not necessarily based on common
    > sense. And don't tell me that having a C interface is not a marketing
    > decision.
    > </offtopic>



    Sometimes it is just a case that certain developers at the company who
    are "afraid" to use C++. Sounds silly, yes. But we all cannot control
    everybody :(

    -shez-
    Shezan Baig, Jun 9, 2005
    #9
  10. Vincezo Ciaschini

    Pete Becker Guest

    Victor Bazarov wrote:
    >
    > And don't tell me that having a C interface is not a marketing
    > decision.
    >


    It's often a sensible engineering decision. C interfaces are far less
    dependent on the compiler you're using than C++ interfaces, so a shared
    library with a C interface is more broadly useful than a shared library
    with a C++ interface. Having a well-defined C++ ABI for the platform
    you're targeting makes this less of a problem, to the extent that the
    ABI really is well-defined.

    --

    Pete Becker
    Dinkumware, Ltd. (http://www.dinkumware.com)
    Pete Becker, Jun 9, 2005
    #10
  11. Vincezo Ciaschini

    Rapscallion Guest

    Vincezo Ciaschini wrote:
    > Supposing you have the following declaration in a header file:
    > -- head.h --

    ....
    >
    > Is this legal/portable?


    Maybe. But the classic way to provide a C interface for a C++ program
    goes like this:

    // somefile.h ----------------------
    struct s; // declaration

    extern "C" {
    struct s *create(void);
    void destroy (struct s* x);
    void method1 (struct s* x, int);
    // ...
    }


    // somefile.cpp --------------------
    struct s {
    s();
    s(double);
    method1(int);
    method2(float);
    private:
    int c;
    char v;
    };

    s *create(void)
    {
    struct s *res = new s(1.0);
    res->method1(4);
    return res;
    }

    void destroy (struct s* x) { ... }
    void method1 (struct s* x, int) { ... }


    // the C user ------------------------
    int main() {
    struct s* val = create();
    method1 (s, 33);
    destroy (s);
    }
    Rapscallion, Jun 9, 2005
    #11
  12. Vincezo Ciaschini

    Andre Kostur Guest

    Victor Bazarov <> wrote in news:8oYpe.81965
    $01.us.to.verio.net:

    > Vincezo Ciaschini wrote:
    >> Supposing you have the following declaration in a header file:
    >> -- head.h --
    >>
    >> struct s {
    >> int c;
    >> char v;
    >> #if defined(__cplusplus)
    >> s();
    >> s(double);
    >> method1(int);
    >> method2(float);
    >> #endif
    >> };
    >>
    >> and then two sources,
    >>
    >> -- cppsrc.cc --
    >> #include "head.h"
    >>
    >> extern "C" {
    >> s *create(void)
    >> {
    >> s *res = new s(1.0);
    >> res->method1(4);
    >> return res;
    >> }
    >>
    >> -- csrc.c --
    >> #include "head.h"
    >>
    >> extern struct s *create(void);
    >>
    >> int f()
    >> {
    >> struct s* val = create();
    >> val->v = 'd';
    >> }
    >>
    >> Is this legal/portable?

    >
    > I have no definite answer to this question. I believe, though, that
    > it would be implementation-specific. However, regardless of what I
    > believe, I'd like to know *why* would you want to do something like
    > that. Why do you feel the need to have both C and C++ translation

    units
    > in the same program?


    Arguably wouldn't that violate the One Definition Rule ?
    Andre Kostur, Jun 9, 2005
    #12
  13. On 9 Jun 2005 08:37:17 -0700, Rapscallion wrote:
    > Vincezo Ciaschini wrote:
    >> Supposing you have the following declaration in a header file:
    >> -- head.h --

    > ...
    >>
    >> Is this legal/portable?

    >
    > Maybe. But the classic way to provide a C interface for a C++ program
    > goes like this:
    >
    > // somefile.h ----------------------
    > struct s; // declaration
    >
    > extern "C" {
    > struct s *create(void);
    > void destroy (struct s* x);
    > void method1 (struct s* x, int);
    > // ...
    > }
    >
    >
    > // somefile.cpp --------------------
    > struct s {
    > s();
    > s(double);
    > method1(int);
    > method2(float);
    > private:
    > int c;
    > char v;
    > };
    >
    > s *create(void)
    > {
    > struct s *res = new s(1.0);


    This new could throw an exception. You should use the one that returns a
    NULL pointer on error and handle that case.

    > res->method1(4);
    > return res;
    > }
    >
    > void destroy (struct s* x) { ... }
    > void method1 (struct s* x, int) { ... }
    >
    >
    > // the C user ------------------------
    > int main() {
    > struct s* val = create();
    > method1 (s, 33);
    > destroy (s);
    > }
    >



    --
    I'm not a racist. I hate everyone equally!
    Rene Moehring, Jun 10, 2005
    #13
  14. Vincezo Ciaschini

    Rapscallion Guest

    Rene Moehring wrote:
    > On 9 Jun 2005 08:37:17 -0700, Rapscallion wrote:

    ....
    > > s *create(void)
    > > {
    > > struct s *res = new s(1.0);

    >
    > This new could throw an exception. You should use the one that returns a
    > NULL pointer on error and handle that case.
    >
    > > res->method1(4);
    > > return res;
    > > }


    Good point. Not only new may throw but also 'res->method1(4)'. One
    needs to surround function bodies with try {} catch (...){} blocks.
    Rapscallion, Jun 10, 2005
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    1
    Views:
    564
    John Timney \(MVP\)
    Jun 19, 2006
  2. Chris Fogelklou
    Replies:
    36
    Views:
    1,358
    Chris Fogelklou
    Apr 20, 2004
  3. Replies:
    7
    Views:
    420
  4. aling
    Replies:
    8
    Views:
    944
    Pete Becker
    Oct 19, 2005
  5. joe

    struct memory layout

    joe, Jan 22, 2008, in forum: C++
    Replies:
    2
    Views:
    347
    EventHelix.com
    Jan 23, 2008
Loading...

Share This Page