当前位置: 首页 > 知识库问答 >
问题:

将结构数组传递给Perl 6 NativeCall函数

党建义
2023-03-14

我正在尝试使用NativeCall与一些C函数交互。

我有一个简单的C结构,以及一个想要它们数组的函数。

struct foo {
    int x;
    char *s;
};

struct foo foo_array[3];

foo_array[0].x = 12;
foo_array[0].s = "foo";
foo_array[1].x = 27;
foo_array[1].s = "bar";
foo_array[2].x = -1;

void somefunc(foo_array);

我试过很多方法,但似乎都做不好。

class foo is repr('CStruct') {
    has int32 $.x;
    has Str $.s
};

sub somefunc(CArray[foo]) is native { * }

my @foo-array := CArray[foo].new;

@foo-array[0] = ???
@foo-array[1] = ???
@foo-array[2] = ???

somefunc(@foo-array);

如何正确创建foo类的对象并设置它们的值,以及如何使它们的数组适合传递?

共有2个答案

万明辉
2023-03-14

下面的代码显示了如何将指向字节的指针和指向wchar的指针传递给windows api函数。

我还没有需要传入结构数组的情况,但我不明白为什么相同的技术不适用。最重要的是:您必须确保为数据分配内存

use NativeCall;

constant UINT    := uint32;
constant BOOL    := uint32;
constant BYTE    := uint8;
constant WCHAR   := uint16;
constant int     := int32;

constant LPWTSTR      := CArray[WCHAR];
constant PBYTE        := CArray[BYTE];

my $virtual-keycode = 0xBC; # comma

sub SetConsoleCP(UINT) is native('Kernel32') returns BOOL { * };
sub SetConsoleOutputCP(UINT) is native('Kernel32') returns BOOL { * };

# winapi: int ToUnicode( UINT wVirtKey, UINT wScanCode, const PBYTE lpKeyState, LPWSTR pwszBuff, int cchBuff, UINT wFlags );
sub ToUnicode(UINT, UINT, PBYTE is rw, LPWTSTR is rw, int32, UINT) is native("User32") returns int32 { * };

my @kbs := CArray[BYTE].new(0 xx 256);
my @buf := CArray[WCHAR].new(0 xx 2);

say "Can't set Codepage" unless SetConsoleCP(65001) && SetConsoleOutputCP(65001);

say "Got Unicode" ~ @buf[0] ~ " -> " ~ @buf[0].chr
    if ToUnicode( $virtual-keycode, 0, @kbs, @buf, 2 ,0);   
柳飞鸾
2023-03-14

据我所知,没有内置的方法来做到这一点。然而,有足够的绳子来上吊构建一个解决方法:

role StructArray[Mu:U \T where .REPR eq 'CStruct'] does Positional[T] {
    has $.bytes;
    has $.elems;

    method new(UInt \n) {
        self.bless(bytes => buf8.allocate(n * nativesizeof T), elems => n);
    }

    method AT-POS(UInt \i where ^$!elems) {
        nativecast(T, Pointer.new(nativecast(Pointer, $!bytes) + i * nativesizeof T));
    }

    method pointer {
        nativecast(Pointer[T], $!bytes);
    }
}

这应允许以下操作:

my @foo-array := StructArray[foo].new(10); # 'array' with 10 elements
@foo-array[0].x = 42;

通过传递foo数组,可以与C函数进行交互。指向类型为指针[foo]的参数的指针。由于结构也是通过指针传递的,您还可以将foo数组[0]传递给类型为foo的参数,以获得相同的效果。

 类似资料:
  • 要将数组参数传递给函数,需指定不带方括号的数组名。例如,如果数组hourlyTemperatures声明如下: int hourlyTemperatures[24]; 则下列函数调用语句: modifyArray(hourlyTemperatutes,24); 将数组 hourlyTemperatures 及其长度传递给函数 modifyArray。将数组传递给函数时,通常也将其长度传递给函数,使

  • 我创建了一个Author对象,用于构造函数的方法签名:public Book但是,我所做的赋值要求将Author(实例变量)更改为。当然,现在我以前的构造函数不行了。这是密码 如果我上传的方式不令人满意,我对任何不便表示歉意。我还没有学会使用堆栈溢出。 谢谢!

  • 我正在使用一个第三方库函数,它有大量的位置参数和命名参数。在我的代码中,从多个点使用相同的参数/值调用该函数。 为了便于维护,我不想在代码中多次硬编码几十个相同的参数。我希望有一种方法可以在数据结构中存储它们一次,所以我只需要传递数据结构。按照以下思路: 假设我调用的函数的签名如下: 假设在我的代码中,我想用 for arg1, for arg2 for arg4 (而且我没有使用arg3)。 我

  • Java枚举允许您将参数传递给构造函数,但我似乎不能传递数组。例如,下面的代码编译时有错误: 但如果将相同的数据作为数组常量传入,则代码将无法编译: 我也尝试过创建新的int[]数组的变体,比如: 没有运气。我认为问题在于传递一个数组常量。我不确定这是一个需要修正的简单语法,还是在传递这种类型的数据时存在一个潜在的问题。提前道谢。

  • 问题内容: 我想将功能传递给子组件,但出现此错误。 基本上是我想做的。 var ReactGridLayout = require(’react-grid-layout’); 似乎它是在React v16中引入的。因此,将函数从父代传递给子代的正确方法是什么? 问题答案: 我发现出了什么问题。这是因为react-grid-layout。我必须将其余的属性传递给孩子。

  • 问题内容: 在处理中,我定义了以下类: 现在,我想创建该类的实例,但是我很难将数组传递给构造函数: 但这总是给我一个错误“意外令牌:{”。因此,显然无法“即时”定义数组。 但是,这将起作用: 但是我发现在对象外部声明该数组是很愚蠢的,因为这会在创建多个对象时带来各种麻烦: 现在,该类的两个实例都引用了相同的数组,这当然不是我想要的。 所以我的问题是:如何在不事先声明数组的情况下将数组正确传递给类的