화요일, 9월 29, 2009

pass struct to char pointer(char*) in DLL export function

DLL 에서 export 된 function parameter 로 struct 를 char pointer (char*) 로 전달
( pass struct to char pointer(char*) in DLL export function )

DLL: int testFunc(int a, int* b = 0, char* _items = 0);
exe: struct 변수를 memcpy 로 char type 의 buffer 에 넣어서 buffer address 를 char* 에 넘긴다.

아래는 test code 다.
꼭 사용할 때면 새로 작성을 해서 테스트를 하다보니 여기에 그냥 적어 놓는다. 에휴...

참고로, Delphi 에서 struct 를 char* 로 전달 할 때는 다음과 같이 하자.
int* 는 Pointer( @_array_var_[0] {trick} );
char* 거나 struct 를 char* 로 전달할 때는 PChar(@_struct_var); 이렇게 사용하자.

--- Delphi ---
type
TSubItem = packed record
str: string;
a: integer;
end;
TItems = packed record
flag: boolean;
item1: TSubItem;
item2: TSubItem;
end;
TDllFunc_ = function (...; intArray: Pointer; pStr: PChar;...): HResult; cdecl;
TIntArray = array[0..3] of integer;

var
g_Items: TItems;
g_IntArray: TIntArray;

implementation
//{$R *.dfm}

procedure aaa;
var
...
DllFunc: TDllFunc_;
begin
...
g_IntArray[0] := 1;
g_IntArray[1] := 2;
g_IntArray[2] := 3;
DllFunc( ..., Pointer(@g_IntArray[0]{trick}), PChar(@g_Items), ... );
end;


//
// C/C++
//

--- DLL: test.c ---
#include "windows.h"
#include "iostream"

#define EXTC_API extern "C"
#define CLIB_API /*extern "C"*/ __declspec(dllexport)

extern "C" {
#pragma pack(push)
#pragma pack(1)
typedef struct {
char* pStr;
int a;
int b;
} item_st;

typedef struct {
boolean enableItem1;
boolean enableItem2;
boolean enableItem3;
item_st item1;
item_st item2;
item_st item3;
} items_st;
#pragma pack(pop)
}

EXTC_API CLIB_API int testFunc(int a, int* b = 0, char* _items = 0);

/*static*/ items_st* items = NULL;
EXTC_API CLIB_API int testFunc(int a, int* b, char* _items) {
items = (items_st*)_items; // 'items': Global STATIC variable

for( int i = 0; i < 3; i++ ) fprintf( fp, "[%d] = %d\n", i, *(b+i) ); fprintf( stdout, "%d, %d, %d\n", items->enableItem1, items->enableItem2, items->enableItem3 );
fprintf( stdout, "%s, %d, %d\n", items->item1.pStr, items->item1.a, items->item1.b );
fprintf( stdout, "%s, %d, %d\n", items->item2.pStr, items->item2.a, items->item2.b );
fprintf( stdout, "%s, %d, %d\n", items->item3.pStr, items->item3.a, items->item3.b );

return 0;
}

--- EXE: test_bin.c ---
#include "windows.h"
#include "iostream"

#pragma pack(push)
#pragma pack(1)
typedef struct {
char* pStr;
int a;
int b;
} item_st;

typedef struct {
boolean enableItem1;
boolean enableItem2;
boolean enableItem3;
item_st item1;
item_st item2;
item_st item3;
} items_st;
#pragma pack(pop)

typedef int (*gFP)(int, int*, char*);
int myFunc(void);
int main(void) {
int ret = 0;
ret = myFunc();
return ret;
}
int myFunc(void) {
int ret = 0;
HINSTANCE hInst;

hInst = LoadLibrary("test.dll");

if( !hInst ) {
fprintf( stderr, "[ERROR] Cannot open test.dll\n" );
return 1;
}

gFP gfp = (gFP)GetProcAddress( hInst, "testFunc" );

{
int bufInt[3] = { 0, 1, 2 };
char bufStrItems[sizeof(items_st)] = { 0 };

items_st items = { 0 };
items.enableItem1 = TRUE;
items.enableItem2 = TRUE;
items.enableItem3 = TRUE;

items.item1.pStr = "AAAAABBBBB";
items.item1.a = 10;
items.item1.b = 10;

items.item2.pStr = "CCCCCDDDDD";
items.item2.a = 20;
items.item2.b = 20;

items.item3.pStr = "EEEEEFFFFF";
items.item3.a = 30;
items.item3.b = 30;

memcpy( bufStrItems, &items, sizeof(items_st) );
ret = gfp( 0, (int*)&bufInt, bufStrItems );
}

if( ret )
fprintf( stdout, "Success\n" );
else
fprintf( stderr, "Fail\n" );

FreeLibrary( hInst );

return (ret ? true : false);
}

-----
Cheers,
June

댓글 없음:

댓글 쓰기