2016-02-06 206 views
6

我有以下结构:NativeCall结构包含指针

typedef struct _info{ 
    DWORD myInfo; 
    BYTE *pInfo; 
    LPWSTR ExtData; 

} Info; 

我代表这个结构使用NativeCall这样的:

class Info is repr('CStruct') { 
    has int32 $.myInfo; 
    has Pointer[int8] $.pInfo ; 
    has Pointer[int16] $.ExtData; 
} 

难道这表示好吗?如何访问和设置$.pInfo指向的数据?

回答

3

的表现似乎没给我...鉴于这种发明了C库: (请不要挑我的C富 - 其旁边的点)

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

typedef unsigned long int DWORD; 
typedef unsigned char BYTE; 
typedef char * LPWSTR; 

typedef struct _info{ 
    DWORD myInfo; 
    BYTE *pInfo; 
    LPWSTR ExtData; 
} Info; 


Info* create_info(); 
void display_info(); 
void double_info(Info*); 

Info* 
create_info() { 
    DWORD init_myinfo = 2016; 
    BYTE init_pinfo  = 37; 
    char init_ExtData[] = "Hello World"; 

    Info *new_info = malloc(sizeof(Info)); 
    if (new_info == NULL) { 
     printf("Memory alloc failed\n"); 
     exit(1); 
    } 

    new_info->myInfo = init_myinfo; 

    BYTE *pinfo = malloc(sizeof(BYTE)); 
    *pinfo = init_pinfo; 
    new_info->pInfo = pinfo; 

    char *ext_data = malloc(sizeof(init_ExtData)); 
    strcpy(ext_data, init_ExtData); 
    new_info->ExtData = ext_data; 

    return new_info; 
} 

void 
display_info(Info *inf) { 
    printf("myInfo: %lu\n", inf->myInfo); 
    printf("pInfo: %i\n", *inf->pInfo); 
    printf("ExtData: %s\n", inf->ExtData); 
} 

void 
double_info(Info *inf) { 

    inf->myInfo *= 2; 

    if (*(inf->pInfo) < 128) 
     *(inf->pInfo) *= 2; 

    int extdata_len = strlen(inf->ExtData); 
    char *tmp_extdata = malloc(extdata_len * 2 + 2); 
    strncpy(tmp_extdata, inf->ExtData, extdata_len); 
    tmp_extdata[extdata_len] = '+'; 
    strcpy(&tmp_extdata[extdata_len+1], inf->ExtData); 
    inf->ExtData = tmp_extdata; 
} 

然后使用NativeCall您perl6的结构定义或多或少的作品:

#!/usr/bin/env perl6 
use NativeCall; 

class Info is repr('CStruct') { 
    has int32   $.myInfo; 
    has Pointer[int8] $.pInfo ; 
    has Pointer[Str] $.ExtData; 

    method Str { 
     qq:to/END HERE/; 
     myInfo: $!myInfo 
     pInfo: { $!pInfo.deref } 
     ExtData: { $!ExtData.deref } 
     END HERE 
    } 
} 

our sub create_info() returns Info is native('pinfo') { * } 
our sub display_info(Info) is native('pinfo') { * } 
our sub double_info(Info is rw) is native('pinfo') { * } 

my Info $inf = create_info(); 
say 'Displaying $inf after calling create_info()'; 
display_info $inf; 

double_info $inf; 
say 'Displaying $inf after calling double_info()'; 
display_info $inf; 

say 'Displaying $inf by calling attribute methods on Perl6 object'; 
say "myInfo: $inf.myInfo()"; 
say "pInfo: $inf.pInfo.deref()"; 
say "ExtData: $inf.ExtData.deref()"; 

say 'Displaying $inf by stringifying Perl6 object'; 
say "$inf"; 
exit 0; 

这样的运行产生;

Displaying $inf after calling create_info() 
myInfo: 2016 
pInfo: 37 
ExtData: Hello World 
Displaying $inf after calling double_info() 
myInfo: 4032 
pInfo: 74 
ExtData: Hello World+Hello World 
Displaying $inf by calling attribute methods on Perl6 object 
myInfo: 4032 
pInfo: 74 
ExtData: Hello World+Hello World 
Displaying $inf by stringifying Perl6 object 
myInfo: 4032 
pInfo: 74 
ExtData: Hello World+Hello World 

或者,可以隐藏多个perl6类内的“胶水”的;

#!/usr/bin/env perl6 
use NativeCall; 

class Info is repr('CStruct') { 
    has int32   $.myInfo is rw ; 
    has Pointer[int8] $!pInfo ; 
    has Pointer[Str] $!ExtData ; 

    my sub create_info() returns Info is native('pinfo') { * } 
    my sub display_info(Info)   is native('pinfo') { * } 
    my sub double_info(Info is rw) is native('pinfo') { * } 

    method new  { create_info()  } 
    method display { display_info(self) } 
    method double { double_info(self) } 

    method pInfo { $!pInfo.deref  } 
    method ExtData { $!ExtData.deref } 

    method Str { 
     qq:to/END HERE/; 
     myInfo: { self.myInfo } 
     pInfo: { self.pInfo } 
     ExtData: { self.ExtData } 
     END HERE 
    } 
} 

my Info $inf .= new; 
say 'Displaying $inf after calling .new'; 
$inf.display ; 

$inf.double ; 
say 'Displaying $inf after calling .double'; 
$inf.display ; 

say 'Displaying $inf by calling attribute methods on Perl6 object'; 
say "myInfo: $inf.myInfo()"; 
say "pInfo: $inf.pInfo()"; 
say "ExtData: $inf.ExtData()"; 

$inf.myInfo = 12046 ; 
say 'Displaying $inf by stringifying Perl6 object'; 
say "$inf"; 
exit 0; 

...一个更清洁的外观。它同样产生;

Displaying $inf after calling .new 
myInfo: 2016 
pInfo: 37 
ExtData: Hello World 
Displaying $inf after calling .double 
myInfo: 4032 
pInfo: 74 
ExtData: Hello World+Hello World 
Displaying $inf by calling attribute methods on Perl6 object 
myInfo: 4032 
pInfo: 74 
ExtData: Hello World+Hello World 
Displaying $inf by stringifying Perl6 object 
myInfo: 12046 
pInfo: 74 
ExtData: Hello World+Hello World 

注:

(1)你叫上指针类型的属性.deref()方法获取的实际数据所指向。

(2)NativeCall documentation必须读不止一次;-)

(3)不管是什么我想,我不能修改通过指针所引用的数据 - 我一直得到“可以”修改不可变数据“。

(4)YMMV