PinvokeLib.dll

Mise à jour : novembre 2007

Le code suivant définit les fonctions de bibliothèque fournies par Pinvoke.dll. Plusieurs exemples décrits dans cette section appellent cette bibliothèque.

Exemple

// Interop.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "PinvokeLib.h"
#include <strsafe.h>
#include <objbase.h>
#include <stdio.h>

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                )
{
    switch (ul_reason_for_call)
   {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
         break;
    }
    return TRUE;
}

// This is the constructor of a class that has been exported.
CTestClass::CTestClass()
{ 
   m_member = 1; 
}

int CTestClass::DoSomething( int i )
{
   return i*i + m_member;
}

extern "C" PINVOKELIB_API CTestClass* CreateTestClass()
{
   return new CTestClass();
}

extern "C" PINVOKELIB_API void DeleteTestClass( CTestClass* instance )
{
   delete instance;
}

//******************************************************************

extern "C" PINVOKELIB_API int TestArrayOfInts( int* pArray, int size )
{
   int result = 0;

   for( int i = 0; i < size; i++ )
   {
      result += pArray[ i ];
      pArray[ i ] += 100;
   }
   return result;
}
//******************************************************************

extern "C" PINVOKELIB_API int TestRefArrayOfInts( int** ppArray, int* pSize )
{
   int result = 0;

   // CoTaskMemAlloc must be used instead of the new operator
   // because code on the managed side will call Marshal.FreeCoTaskMem 
   // to free this memory.
   
   int* newArray = (int*)CoTaskMemAlloc( sizeof(int) * 5 );

   for( int i = 0; i < *pSize; i++ )
   {
      result += (*ppArray)[ i ];
   }

   for( int j = 0; j < 5; j++ )
   {
      newArray[ j ] = (*ppArray)[ j ] + 100;
   }

   CoTaskMemFree( *ppArray );
   *ppArray = newArray;
   *pSize = 5;

   return result;
}
//******************************************************************

extern "C" PINVOKELIB_API int TestMatrixOfInts( int pMatrix[][COL_DIM], int row )
{
   int result = 0;

   for( int i = 0; i < row; i++ )
   {
      for( int j = 0; j < COL_DIM; j++ )
      {
         result += pMatrix[ i ][ j ];
         pMatrix[ i ][ j ] += 100;
      }
   }
   return result;
}
//******************************************************************

extern "C" PINVOKELIB_API int TestArrayOfStrings( char* ppStrArray[], int size )
{
   int result = 0;
   STRSAFE_LPWSTR temp;

   for( int i = 0; i < size; i++ )
   {
      result += strlen( ppStrArray[ i ] );

      temp = (STRSAFE_LPWSTR)CoTaskMemAlloc( sizeof(char) * 10 );
      StringCchCopy( temp, sizeof(temp), (STRSAFE_LPWSTR)"123456789" );

      // CoTaskMemFree must be used instead of delete to free memory.

      CoTaskMemFree( ppStrArray[ i ] );
      ppStrArray[ i ] = (char *) temp;
   }
   return result;
}
//******************************************************************

extern "C" PINVOKELIB_API int TestArrayOfStructs( MYPOINT* pPointArray, int size )
{
   int result = 0;
   MYPOINT* pCur = pPointArray;

   for( int i = 0; i < size; i++ )
   {
      result += pCur->x + pCur->y;
      pCur->y = 0;
      pCur++;
   }
   return result;
}
//******************************************************************

extern "C" PINVOKELIB_API int TestArrayOfStructs2( MYPERSON* pPersonArray, int size )
{
   int result = 0;
   MYPERSON* pCur = pPersonArray;
   STRSAFE_LPWSTR temp;

   for( int i = 0; i < size; i++ )
   {
      result += strlen( pCur->first ) + strlen( pCur->last );

      temp = (STRSAFE_LPWSTR)CoTaskMemAlloc( sizeof(char) * ( strlen( pCur->last ) + 2 ));
      StringCchCopy( temp, sizeof(temp), (STRSAFE_LPWSTR)"Mc" );
      StringCbCat( temp, sizeof(temp), (STRSAFE_LPWSTR)pCur->last );

      // CoTaskMemFree must be used instead of delete to free memory.

      CoTaskMemFree( pCur->last );
      pCur->last = (char *)temp;

      pCur++;
   }
   return result;
}

//******************************************************************
extern "C" PINVOKELIB_API int TestStructInStruct( MYPERSON2* pPerson2 )
{
   STRSAFE_LPWSTR temp = (STRSAFE_LPWSTR)CoTaskMemAlloc( sizeof(char) * ( strlen( pPerson2->person->last ) + 2 ));
   StringCchCopy( temp, sizeof(temp), (STRSAFE_LPWSTR)"Mc" );
   StringCbCat( temp, sizeof(temp), (STRSAFE_LPWSTR)pPerson2->person->last );

   CoTaskMemFree( pPerson2->person->last );
   pPerson2->person->last = (char *)temp;

   return pPerson2->age;
}

//******************************************************************

extern "C" PINVOKELIB_API void TestStructInStruct3( MYPERSON3 person3 )
{
   printf( "\n\nperson passed by value:\n" );
   printf( "first = %s last = %s age = %i\n\n", 
      person3.person.first, person3.person.last, person3.age );
}

//*********************************************************************

extern "C" PINVOKELIB_API void TestUnion( MYUNION u, int type )
{
   if(( type != 1 ) && ( type != 2 )) return;
   if( type == 1 )
      printf( "\n\ninteger passed: %i", u.i );
   else if( type == 2 )
      printf( "\n\ndouble passed: %f", u.d );
}
//******************************************************************

extern "C" PINVOKELIB_API void TestUnion2( MYUNION2 u, int type )
{
   if(( type != 1 ) && ( type != 2 )) return;
   if( type == 1 )
      printf( "\n\ninteger passed: %i", u.i );
   else if( type == 2 )
      printf( "\n\nstring passed: %s", u.str );
}
//******************************************************************

extern "C" PINVOKELIB_API void TestCallBack( FPTR pf, int value )
{
   printf( "\nReceived value: %i", value );
   printf( "\nPassing to callback..." );
   bool res = (*pf)(value);
   
   if( res )
      printf( "Callback returned true.\n" );
   else
      printf( "Callback returned false.\n" );
}
//******************************************************************

extern "C" PINVOKELIB_API void TestCallBack2( FPTR2 pf2, char* value )
{
   printf( "\nReceived value: %s", value );
   printf( "\nPassing to callback..." );
   bool res = (*pf2)(value);
   
   if( res )
      printf( "Callback2 returned true.\n" );
   else
      printf( "Callback2 returned false.\n" );
}

//******************************************************************

extern "C" PINVOKELIB_API void TestStringInStruct( MYSTRSTRUCT* pStruct )
{
   wprintf( L"\nUnicode buffer content: %s\n", pStruct->buffer );

   // Assuming that the buffer is big enough.
   StringCbCat( pStruct->buffer, sizeof(pStruct->buffer), L"++" );
}

//******************************************************************

extern "C" PINVOKELIB_API void TestStringInStructAnsi( MYSTRSTRUCT2* pStruct )
{
   printf( "\nAnsi buffer content: %s\n", pStruct->buffer );

   // Assuming that the buffer is big enough.
   StringCbCat( (STRSAFE_LPWSTR) pStruct->buffer, sizeof(pStruct->buffer), (STRSAFE_LPWSTR)"++" );
}

//******************************************************************

extern "C" PINVOKELIB_API void TestOutArrayOfStructs( int* pSize, MYSTRSTRUCT2** ppStruct )
{
   const int cArraySize = 5;
   *pSize = cArraySize;
   *ppStruct = (MYSTRSTRUCT2*)CoTaskMemAlloc( cArraySize * sizeof( MYSTRSTRUCT2 ));

   MYSTRSTRUCT2* pCurStruct = *ppStruct;
   STRSAFE_LPWSTR buffer;
   for( int i = 0; i < cArraySize; i++, pCurStruct++ )
   {
      pCurStruct->size = i;
      buffer = (STRSAFE_LPWSTR)CoTaskMemAlloc( 4 );
      StringCchCopy( buffer, sizeof(buffer), (STRSAFE_LPWSTR)"***" );
      pCurStruct->buffer = (char *)buffer;
   }
}
//************************************************************************
extern "C" PINVOKELIB_API char * TestStringAsResult()
{
   STRSAFE_LPWSTR result = (STRSAFE_LPWSTR)CoTaskMemAlloc( 64 );
   StringCchCopy( result, sizeof(result) , (STRSAFE_LPWSTR)"This is return value" );
   return (char *) result;
}

//************************************************************************
extern "C" PINVOKELIB_API void SetData( DataType typ, void* object )
{
   switch( typ )
   {
      case DT_I2: printf( "Short %i\n", *((short*)object) ); break;
      case DT_I4: printf( "Long %i\n", *((long*)object) ); break;
      case DT_R4: printf( "Float %f\n", *((float*)object) ); break;
      case DT_R8: printf( "Double %f\n", *((double*)object) ); break;
      case DT_STR: printf( "String %s\n", (char*)object ); break;
      default: printf( "Unknown type" ); break;
   }
}
//************************************************************************
extern "C" PINVOKELIB_API void TestArrayInStruct( MYARRAYSTRUCT* pStruct )
{
   pStruct->flag = true;
   pStruct->vals[ 0 ] += 100;
   pStruct->vals[ 1 ] += 100;
   pStruct->vals[ 2 ] += 100;
}
//************************************************************************

// PinvokeLib.h : The header file for the DLL application.
//
// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the PINVOKELIB_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// PINVOKELIB_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef PINVOKELIB_EXPORTS
#define PINVOKELIB_API __declspec(dllexport)
#else
#define PINVOKELIB_API __declspec(dllimport)
#endif

// This class is exported from the PinvokeLib.dll
class PINVOKELIB_API CTestClass 
{
public:
CTestClass( void );
int DoSomething( int i );
private:
int m_member;
};

extern "C" PINVOKELIB_API CTestClass* CreateTestClass();
extern "C" PINVOKELIB_API void DeleteTestClass( CTestClass* instance );

//*************************************************************************************

extern "C" PINVOKELIB_API int TestArrayOfInts( int* pArray, int size );

extern "C" PINVOKELIB_API int TestRefArrayOfInts( int** ppArray, int* pSize );

const int COL_DIM = 5;
extern "C" PINVOKELIB_API int TestMatrixOfInts( int pMatrix[][COL_DIM], int row );

extern "C" PINVOKELIB_API int TestArrayOfStrings( char* ppStrArray[], int size );
//*************************************************************************************

typedef struct _MYPOINT
{
int x; 
int y; 
} MYPOINT;

extern "C" PINVOKELIB_API int TestArrayOfStructs( MYPOINT* pPointArray, int size );
//*************************************************************************************

typedef struct _MYPERSON
{
char* first; 
char* last; 
} MYPERSON;

extern "C" PINVOKELIB_API int TestArrayOfStructs2( MYPERSON* pPersonArray, int size );
//*************************************************************************************

typedef struct _MYPERSON2
{
MYPERSON* person;
int age; 
} MYPERSON2;

extern "C" PINVOKELIB_API int TestStructInStruct( MYPERSON2* pPerson2 );
//*************************************************************************************

typedef struct _MYPERSON3
{
MYPERSON person;
int age; 
} MYPERSON3;

extern "C" PINVOKELIB_API void TestStructInStruct3( MYPERSON3 person3 );
//*************************************************************************************

union MYUNION
{
    int i;
    double d;
};

extern "C" PINVOKELIB_API void TestUnion( MYUNION u, int type );

union MYUNION2
{
    int i;
    char str[128];
};

extern "C" PINVOKELIB_API void TestUnion2( MYUNION2 u, int type );
//*************************************************************************************

typedef bool (CALLBACK *FPTR)( int i );
extern "C" PINVOKELIB_API void TestCallBack( FPTR pf, int value );

typedef bool (CALLBACK *FPTR2)( char* str );
extern "C" PINVOKELIB_API void TestCallBack2( FPTR2 pf2, char* value );

//*************************************************************************************

typedef struct _MYSTRSTRUCT
{
wchar_t* buffer;
UINT size; 
} MYSTRSTRUCT;

// buffer is an in/out param
extern "C" PINVOKELIB_API void TestStringInStruct( MYSTRSTRUCT* pStruct );

typedef struct _MYSTRSTRUCT2
{
char* buffer;
UINT size; 
} MYSTRSTRUCT2;

// buffer is in/out param
extern "C" PINVOKELIB_API void TestStringInStructAnsi( MYSTRSTRUCT2* pStruct );

extern "C" PINVOKELIB_API void TestOutArrayOfStructs( int* pSize, MYSTRSTRUCT2** ppStruct );

//*************************************************************************************

extern "C" PINVOKELIB_API char* TestStringAsResult();

//*************************************************************************************
enum DataType 
{
DT_I2 = 1,
DT_I4,
DT_R4,
DT_R8,
DT_STR
};

extern "C" PINVOKELIB_API void SetData( DataType typ, void* object );

//*************************************************************************************

typedef struct _MYARRAYSTRUCT
{
bool flag;
int vals[ 3 ]; 
} MYARRAYSTRUCT;

extern "C" PINVOKELIB_API void TestArrayInStruct( MYARRAYSTRUCT* pStruct );

//*************************************************************************************

Voir aussi

Concepts

Exemples divers de marshaling