PinvokeLib.dll
Обновлен: Ноябрь 2007
В следующем примере кода определяются функции библиотеки, предоставляемые Pinvoke.dll. Многие из примеров, описанных в этом разделе, вызывают эту библиотеку.
Пример
// 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 );
//*************************************************************************************