<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Sharing a header file between C and C++, and using Qt-specific macros via #ifdef]]></title><description><![CDATA[<p dir="auto">Hi all,</p>
<p dir="auto">For a few days now I've been struggling to understand what exactly is going wrong in my setup. I have a header file that contains code that looks like the following, in two projects which use CMake:</p>
<pre><code>#if defined(Q_MOC_RUN)
#include &lt;QtQml/qqmlregistration.h&gt;
#endif /* Q_MOC_RUN */

#include &lt;stdbool.h&gt;

typedef struct _GetIntStatusResponse_t
{
#if defined(Q_MOC_RUN)
    Q_GADGET

    Q_PROPERTY(bool clearToSend MEMBER getClearToSend)
    Q_PROPERTY(bool error MEMBER getError)
    Q_PROPERTY(bool rsqInterrupt MEMBER getRsqInterrupt)
    Q_PROPERTY(bool rdsInterrupt MEMBER getRdsInterrupt)
    Q_PROPERTY(bool seekTuneCompletedInterrupt MEMBER getSeekTuneCompletedInterrupt)
#endif /* Q_MOC_RUN */

    /* When set, the device is ready to receive the next command */
    bool clearToSend;

    /* When set, the device has encountered an error */
    bool error;

    /* When set, a Received Signal Quality interrupt has been triggered */
    bool rsqInterrupt;

    /* When set, an Radio Data System interrupt has been triggered */
    bool rdsInterrupt;

    /* When set, the Seek/Tune Complete interrupt has been triggered */
    bool seekTuneCompletedInterrupt;
} GetIntStatusResponse_t;
</code></pre>
<p dir="auto">The intent here is that when the C program compiles the header, it only sees the boolean members but when a Qt application does, it also invokes the meta-object complier to generate whatever it needs to in order for the properties to be accessible from a QML element.</p>
<p dir="auto">The header itself is ferried over as a CMake configuration file together with a target file, and <code>target_link_libraries</code> is used to include it to the Qt application. This is enough, and commands like <code>#include "header.h"</code> work without a hitch.</p>
<p dir="auto">Using a debugger I have verified that the structs arrive correctly to the C++ application side: they are read from a byte array sent over USB, and when <code>std::memcpy</code> is used the debugger shows that the content of the structure instance looks correct compared to what Wireshark is showing on the wire. From this I deduce that the data moves correctly between the C program, USB and the C++ application.</p>
<p dir="auto">However, when an instance of the struct is emitted through a signal, and arrives to the QML side it is completely empty i.e. using <code>console.log</code> together with <code>JSON.stringify</code> I get the following the application's console:</p>
<pre><code>qml: Received status report: QVariant(_GetIntStatusResponse_t, )
qml: Stringified: ""
</code></pre>
<p dir="auto">Naturally, if I try to access any of the members I get <code>undefined</code>. The data itself has mysteriously vanished somewhere during the conversion from a C++ instance to a QVariant-wrapped object.</p>
<p dir="auto">I can provide more code and details if necessary but does anyone have any ideas on what could be going wrong? I have tried stepping through the code that comes when I call <code>emit</code> but it goes so deep into how Qt works that I just can't make sense of it.</p>
<p dir="auto">I have already tried the following:</p>
<ul>
<li>Using <code>#ifdef __cplusplus</code> instead; this leads to a number of linker errors related to a function called <code>staticMetaObject</code>, one per struct type</li>
<li>Omitting Qt stuff from the structs in the shared header, and instead defining more struct in the C++ side; this works but seems rather hacky. There must be a way to coax MOC to do my bidding.</li>
<li>Including the shared headers inside <code>qt_add_executable</code>; this has no effect, the properties are still <code>undefined</code>.</li>
</ul>
]]></description><link>https://forum.qt.io/topic/164347/sharing-a-header-file-between-c-and-c-and-using-qt-specific-macros-via-ifdef</link><generator>RSS for Node</generator><lastBuildDate>Wed, 06 May 2026 17:59:58 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/164347.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 28 Feb 2026 20:04:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Sharing a header file between C and C++, and using Qt-specific macros via #ifdef on Sat, 28 Feb 2026 22:08:11 GMT]]></title><description><![CDATA[<p dir="auto">I managed to stumble across a solution. My problem was that the header files provided by the first CMake project have to be explicitly added to the <code>qt_add_executable</code> stanza so that the meta-object compiler picks them up, and when I first tried it the variable I <em>thought</em> I read them to was, in fact, empty.</p>
<p dir="auto">This is why I received so many linker errors when using the <code>ifdef __cplusplus</code> in the header file. The shared header file was being used through an <code>#import</code> statement but for some reason meta-object compiler only processed the header file which included it, not the shared header itself.</p>
<p dir="auto">After noticing that the variable was empty I explicitly added the header files to <code>qt_add_executable</code>, and much to my surprise the linker error is now gone, and everything works.</p>
]]></description><link>https://forum.qt.io/post/836686</link><guid isPermaLink="true">https://forum.qt.io/post/836686</guid><dc:creator><![CDATA[AnttiK]]></dc:creator><pubDate>Sat, 28 Feb 2026 22:08:11 GMT</pubDate></item><item><title><![CDATA[Reply to Sharing a header file between C and C++, and using Qt-specific macros via #ifdef on Sat, 28 Feb 2026 20:44:54 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/sgaist">@<bdi>SGaist</bdi></a> What I'm doing is creating an instance of a "report struct" that uses a union type in the C application, filling the proper portion of that, send it as a HID report, and then parse the bytes on the other side.</p>
<p dir="auto">Here is the glue which makes it work:</p>
<pre><code>typedef struct _Report_t
{
    /* Identifier of the report */
    ReportIdentifier_t identifier;

    /* Report bytes */
    union ReportBytes {
        GetIntStatusResponse_t interruptStatus;
        ... other structs ...

        //* This defines the "maximum size" the report can have; one byte is reserved for the identifier */
        uint8_t raw[MAX_REPORT_SIZE - 1];
    } bytes;
} Report_t;
</code></pre>
<p dir="auto">The relevant portion of the C++ code looks like this. It uses the <code>hidapi</code> library:</p>
<pre><code>unsigned char buf[MAX_REPORT_SIZE];

int res = hid_read_timeout(m_source, buf, sizeof(buf), 250);
if (res &gt; 0)
{
    ReportIdentifier_t identifier = (ReportIdentifier_t)buf[0];

    switch (identifier)
    {
    ... other report types ...

    case REPORT_IDENTIFIER_INTERRUPT_STATUS: {
        GetIntStatusResponse_t report;
        std::memcpy(&amp;report, &amp;buf[1], sizeof(GetIntStatusResponse_t));

        emit intStatusReportReceived(report);

        break;
    }
}
</code></pre>
<p dir="auto">If I look at the report object in debugger, it is correct each and every time. The problems surface once the struct is pushed towards QML with <code>emit</code>.</p>
]]></description><link>https://forum.qt.io/post/836684</link><guid isPermaLink="true">https://forum.qt.io/post/836684</guid><dc:creator><![CDATA[AnttiK]]></dc:creator><pubDate>Sat, 28 Feb 2026 20:44:54 GMT</pubDate></item><item><title><![CDATA[Reply to Sharing a header file between C and C++, and using Qt-specific macros via #ifdef on Sat, 28 Feb 2026 20:23:11 GMT]]></title><description><![CDATA[<p dir="auto">Hi,</p>
<p dir="auto">Do I understand correctly that you are trying to load a binary representation of one struct in C into what is technically a different struct in C++ ?</p>
<p dir="auto"><code>memcpy</code> is the wrong tool here, you should initialize your C++ struct based on the C one. These two have different memory layouts thus overwriting the memory taken by the latter with the former is a recipe for tragedy.</p>
]]></description><link>https://forum.qt.io/post/836682</link><guid isPermaLink="true">https://forum.qt.io/post/836682</guid><dc:creator><![CDATA[SGaist]]></dc:creator><pubDate>Sat, 28 Feb 2026 20:23:11 GMT</pubDate></item></channel></rss>