Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how define C structure: c-linkage and udt

Tags:

c++

visual-c++

I have dll written on language X with C-ABI interface. And I want to use this C-ABI from my c++ program.

I wrote in main.cpp:

extern "C" {
struct Foo {
  const char * const data;
  unsigned len;
};
struct Foo f(void);
}

int main()
{
}

And got warning from compiler (visual c++/15.7.5/windows 7/32bit):

(7): warning C4190: 'f' has C-linkage specified, but returns UDT 'Foo' which is incompatible with C

(7): note: see declaration of 'Foo'

Here godbolt link: https://godbolt.org/g/ztx1kf

I read Error in C++ code linkage: warning C4190: type has C-linkage specified, but returns UDT which is incompatible with C, but in my case I have no "c++ code" at all in my POD struct.

How can I convince compiler that this is not C++ struct Foo, but C struct Foo?

I try to move it to separate header file (.h), but this is change nothing.

If I replace const char * const data with const char * warning disappear, what I also don't understand, but I don't want to change definition of struct.

like image 788
user1244932 Avatar asked Jul 15 '18 11:07

user1244932


People also ask

How to define structure C?

Structures (also called structs) are a way to group several related variables into one place. Each variable in the structure is known as a member of the structure. Unlike an array, a structure can contain many different data types (int, float, char, etc.).

How to write struct in C?

Syntax of structstruct structureName { dataType member1; dataType member2; ... }; For example, struct Person { char name[50]; int citNo; float salary; }; Here, a derived type struct Person is defined.

Why to use structure in C?

We use structures to overcome the drawback of arrays. We already know that arrays in C are bound to store variables that are of similar data types. Creating a structure gives the programmer the provision to declare multiple variables of different data types treated as a single entity.

What is structure in C explain with example?

Structure is a user-defined data type. It works similarly like arrays. Structures help you in grouping items of different types in a single group. It stores the collection of different data types. Each element of structure is known as a member.


1 Answers

The x64 calling convention docs explain that UDTs are returned in eax if they are small enough and fit some criteria:

To return a user-defined type by value in RAX, it must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. It must also have no user-defined constructor, destructor, or copy assignment operator; no private or protected non-static data members; no non-static data members of reference type; no base classes; no virtual functions; and no data members that do not also meet these requirements.

While Foo is a StandardLayout type (and as such we would expect it to work), the const non-static data member makes the copy assignment operator deleted, which is probably what they mean, even if it says "user-defined". This makes it, by the way, a non TrivialType and therefore not a POD in the C++03 sense.

It also exceeds the maximum size, but even if we removed len, the above would still prevent it to be a "POD".

Similarly, the x86 calling convention docs explain something similar:

[...] except for 8-byte structures, which are returned in the EDX:EAX register pair. Larger structures are returned in the EAX register as pointers to hidden return structures. [...] Structures that are not PODs will not be returned in registers.

For instance, a function like the following:

struct Foo
{ 
    const uint32_t x;
};

Foo f(void)
{
    Foo foo = { 12345 };
    return foo;
}

When compiled under x86/x64 C++ mode, Foo is considered a non-POD and therefore eax/rax contains the address of the object as the docs lead us to expect.

However, when compiler under x86/x64 C mode, Foo is considered a POD (we are compiling C) and therefore you will get the uint32_t value directly in eax.

Therefore, calling f from C won't work, even if we set the language linkage to C, which is why the warning appears.

like image 55
Acorn Avatar answered Oct 06 '22 00:10

Acorn