Aviso do compilador (nível 2) C4412

'function': a assinatura de função contém o tipo 'type'; não é seguro passar objetos C++ entre código puro e combinado ou nativo.

Comentários

A opção do compilador /clr:pure foi preterida no Visual Studio 2015 e está sem suporte no Visual Studio 2017. Se você tiver um código que precisa ser puro, recomendamos que você o porte para C#.

O compilador detectou uma situação potencialmente insegura que poderia resultar em um erro de runtime: uma chamada está sendo feita de um compiland /clr:pure para uma função que foi importada por meio de dllimport e a assinatura de função contém um tipo não seguro. Um tipo não será seguro se ele contiver uma função membro ou tiver um membro de dados que seja um tipo não seguro ou uma indireção para um tipo não seguro.

Isso não é seguro devido à diferença nas convenções de chamada padrão entre código puro e nativo (ou misto de nativo e gerenciado). Ao importar (via dllimport) uma função para um compiland /clr:pure, verifique se as declarações de cada tipo na assinatura são idênticas às do compiland que exporta a função (tomando cuidado especial com as diferenças nas convenções de chamada implícitas).

Uma função de membro virtual é especialmente propensa a fornecer resultados inesperados. No entanto, até mesmo uma função não virtual deve ser testada para garantir que você obtenha os resultados corretos. Se você tiver certeza de que está obtendo os resultados corretos, poderá ignorar esse aviso.

O C4412 fica desativado por padrão. Para obter mais informações, confira Avisos do compilador que ficam desativados por padrão e dllexport, dllimport.

Para resolver esse aviso, remova todas as funções do tipo.

Exemplos

O exemplo a seguir gera o erro C4412.

// C4412.cpp
// compile with: /c /W2 /clr:pure
#pragma warning (default : 4412)

struct Unsafe {
   virtual void __cdecl Test();
};

struct Safe {
   int i;
};

__declspec(dllimport) Unsafe * __cdecl func();
__declspec(dllimport) Safe * __cdecl func2();

int main() {
   Unsafe *pUnsafe = func();   // C4412
   // pUnsafe->Test();

   Safe *pSafe = func2();   // OK
}

O exemplo a seguir é um arquivo de cabeçalho que declara dois tipos. O tipo Unsafe não é seguro porque tem uma função de membro.

// C4412.h
struct Unsafe {
   // will be __clrcall if #included in pure compilation
   // defaults to __cdecl in native or mixed mode compilation
   virtual void Test(int * pi);

   // try the following line instead
   // virtual void __cdecl Test(int * pi);
};

struct Safe {
   int i;
};

Este exemplo exporta funções com os tipos definidos no arquivo de cabeçalho.

// C4412_2.cpp
// compile with: /LD
#include "C4412.h"

void Unsafe::Test(int * pi) {
   *pi++;
}

__declspec(dllexport) Unsafe * __cdecl func() { return new Unsafe; }
__declspec(dllexport) Safe * __cdecl func2() { return new Safe; }

A convenção de chamada padrão em uma compilação /clr:pure é diferente de uma compilação nativa. Quando C4412.h é incluído, Test é __clrcall por padrão. Se você compilar e executar este programa (não use /c), o programa gerará uma exceção.

O exemplo a seguir gera o erro C4412.

// C4412_3.cpp
// compile with: /W2 /clr:pure /c /link C4412_2.lib
#pragma warning (default : 4412)
#include "C4412.h"

__declspec(dllimport) Unsafe * __cdecl func();
__declspec(dllimport) Safe * __cdecl func2();

int main() {
   int n = 7;
   Unsafe *pUnsafe = func();   // C4412
   pUnsafe->Test(&n);

   Safe *pSafe = func2();   // OK
}