c++structtypedefstdcall

__stdcall typedef struct


I am writing my first DLL in C++. Using __declspec(dll_export), I am able to read it on Python and C++ using a C wrapper. But I want now to read it on C too, so I have to add now the __stdcall convention. But I don't know how to apply it to a typedef struct. For example:

Projet.h

#pragma once
#include "Projet_inc.h"

class Projet // before, class _declspec(dll_export) Projet
{
public:
    Projet();
    ~Projet();

    int multiply(int arg1, int arg2);
    int result;
};

Projet_inc.h

#ifdef PROJET_EXPORTS
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __declspec(dllimport)
#endif

#define CALLCONV_API __stdcall // before, this line didn't exist

extern "C" // C wrapper
{
    typedef struct Projet Projet; // make the class opaque to the wrapper

    Projet* EXPORT CALLCONV_API cCreateObject(void);
    int EXPORT CALLCONV_API cMultiply(Projet* pDLLobject, int arg1, int arg2);
}

and Projet.cpp

#include "stdafx.h"
#include "Projet.h"

Projet::Projet() {}
Projet::~Projet() {}

int Projet::multiply(int arg1, int arg2) {
    result = arg1 * arg2;
    return result;
}

Projet* EXPORT CALLCONV_API  cCreateObject(void)
{
    return new Projet();
}

int EXPORT CALLCONV_API  cMultiply(Projet* pDLLtest, int arg1, int arg2)
{
    if (!pDLLtest)
        return 0;
    return pDLLtest->multiply(arg1, arg2);
}

On Visual Studio 2017, the compilation return (first lines) :

dir\projet_inc.h(11) : warning C4229: anachronisme utilisé : modificateurs de données ignorés
dir\projet_inc.h(13) :error C2059: erreur de syntaxe : '__declspec(dllimport)'

And MSDN told that for C2059 error, I have to check on the typedef struct first.


Solution

  • Export specifiers apply only to functions and variables. Calling convention specifiers apply only to functions. So type alias (C-style) should look like this:

    typedef struct Projet_I2M Projet_I2M;
    

    Export specification should be infront of declaration:

    EXPORT Projet * CALLCONV_API cCreateObject(void);
    

    You seem to intentionally export C interface so you should prevent C++ exceptions from crossing language boundary.

    extern "C" is should be conditionally included:

    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    #ifdef __cplusplus
    }
    #endif