我有以下结构:
typedef struct _info{
DWORD myInfo;
BYTE *pInfo;
LPWSTR ExtData;
} Info;
Run Code Online (Sandbox Code Playgroud)
我用NativeCall这样表示这个结构:
class Info is repr('CStruct') {
has int32 $.myInfo;
has Pointer[int8] $.pInfo ;
has Pointer[int16] $.ExtData;
}
Run Code Online (Sandbox Code Playgroud)
这个表示好吗?如何访问和设置指向的数据$.pInfo?
我想int addwstr(const wchar_t *wstr);在Perl6中使用ncurses 函数.
我怎么能得到一个传达const wchar_t *wstr的Perl 6签名addwstr?
use v6;
use NativeCall;
constant LIB = 'libncursesw.so.5';
sub addwstr( ? ) returns int32 is native(LIB) is export {*};
Run Code Online (Sandbox Code Playgroud) 我有一个第三方C库,它定义了一个类似于的结构:
struct myStruct {
int a;
int b;
char str1[32];
char str2[32];
};
Run Code Online (Sandbox Code Playgroud)
还有一个函数,它接受一个指向这个结构的指针并填充它.我需要我的Perl6本机调用来提供该结构,然后读取结果.
到目前为止,我已经在Perl6中定义了结构:
class myStruct is repr('CStruct') {
has int32 $.a;
has int32 $.b;
has Str $.str1; # Option A: This won't work as Perl won't know what length to allocate
has CArray[uint8] $.str2; # Option B: This makes more sense, but again how to define length?
# Also, would this allocate the array in place, or
# reference an array that is separately allocated (and therefore not …Run Code Online (Sandbox Code Playgroud) 有没有办法在CStruct中声明一个对象数组?
struct my_struct {
int foo;
int bar;
char somestring[80];
};
class My::Struct is repr('CStruct') {
has int32 $.foo;
has int32 $.bar;
???
}
Run Code Online (Sandbox Code Playgroud)
A CArray[uint8]将是一个char *指针,实际上并不在结构中保留空间.
而不是My::Struct.new,我可能自己做内存(而不是My::Struct.new(),我使用一个buf8.allocate(xxx)并保持句柄,所以GC不收割它,nativecast它到My :: Struct),然后我必须使用指针数学来找到里面的字符串结构等,但似乎应该有一个更简单的方法.
即使它没有完全实现,一个简单的方法说"在这里放80个字节,这里是指针",这将是非常好的.
我正在使用NativeCall接口; 有一个接受回调的C函数,定义如下:
typedef void (* ExifContentForeachEntryFunc) (ExifEntry *, void *user_data);
void exif_content_foreach_entry (ExifContent *content, ExifContentForeachEntryFunc func, void *user_data);
Run Code Online (Sandbox Code Playgroud)
我的第一次采取是:
sub exif_content_foreach_entry(ExifContent $exifcontent, &func (ExifEntry $entry, Buf $data), Buf $user_data) is native(LIB) is export { * }
Run Code Online (Sandbox Code Playgroud)
但是在调用时,此函数会生成错误:
Internal error: unhandled dyncall callback argument type
in method CALL-ME at /opt/rakudo-pkg/share/perl6/sources/24DD121B5B4774C04A7084827BFAD92199756E03 (NativeCall) line 588
Run Code Online (Sandbox Code Playgroud)
如果我忽略user_data参数,一切正常,所以声明的其余部分都没问题:我只是不能将任何额外的数据传递给回调函数.
在其他情况下,我使用Buf将(可能的)二进制数据块传递给C函数并且它工作; 这里的区别是回调函数.知道如何解决这个问题吗?
(使用perl6 2018.03)
我尝试用perl6包装sd-bus,但是函数调用三指针有问题.
来自sd-bus.h
int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable); /* free the results */
Run Code Online (Sandbox Code Playgroud)
尝试原生呼叫
sub sd_bus_list_names(Pointer, Pointer[CArray[Str]] , Pointer[CArray[Str]] ) returns int32 is native('systemd') {*}
Run Code Online (Sandbox Code Playgroud)
我打电话,但我不知道如何对数组(@)获取和激活变量的dereferencies.
谢谢,对不起我的英语
[ 编辑 ]
侏儒回复解决我的问题derefencies指针[CArray [Str]]
这是一个测试代码:
use v6;
use NativeCall;
sub strerror(int32) returns Str is native {*}
sub sd_bus_default_system(Pointer is rw) returns int32 is native('systemd') {*}
sub sd_bus_unref(Pointer) returns Pointer is native('systemd') {*}
sub sd_bus_list_names(Pointer,Pointer[CArray[Str]] is rw, Pointer[CArray[Str]] is rw ) returns int32 is native('systemd') {*}
my Pointer $bus .= new;
my …Run Code Online (Sandbox Code Playgroud) 这些代码段可能看起来很奇怪,这是因为我从原始代码开始并切断了碎片,直到我找到了再现错误的最小指令集.所以忍受明显的无用.有两个perl6模块,一个use是另一个,还有一个程序.这是第一个模块:
unit class test1;
use NativeCall;
use test2;
method test
{
my Pointer[void] $dummy .= new;
}
Run Code Online (Sandbox Code Playgroud)
第二个模块包含在第一个模块中,但实际上并未使用它的任何部分:
unit module test2;
use NativeCall;
class A is repr('CStruct') is export {
has Pointer[void] $.wrongdoer;
has int32 $.a;
}
Run Code Online (Sandbox Code Playgroud)
该程序创建一个test1对象并调用测试方法:
use lib '.';
use test1;
my test1 $t .= new;
$t.test;
Run Code Online (Sandbox Code Playgroud)
该程序输出一个错误,显然是由类test1的方法测试中的赋值引起的:
Type check failed in assignment to $dummy; expected NativeCall::Types::Pointer[NativeCall::Types::void] but got NativeCall::Types::Pointer[NativeCall::Types::void].new(0)
Run Code Online (Sandbox Code Playgroud)
如果我$.wrongdoer在第二个类中注释掉,程序执行时没有错误.我正在运行rakudo 2018.06.这是NativeCall模块中的错误还是其他我看不到的错误?
在该natives.pm6模块中,许多本机类型以这种方式声明:
my native int is repr('P6int') is Int { }
Run Code Online (Sandbox Code Playgroud)
您显然可以以相同的方式使用它,
my native smallish is repr('P6int') is Int is nativesize(8) { };
say smallish.^mro; # OUTPUT: «((smallish) (Int) (Cool) (Any) (Mu))?»
Run Code Online (Sandbox Code Playgroud)
显然,您需要native指定一个表示,因为如果native不使用它将失败.同样的is repr,所以他们齐头并进.然而,这只是一种行为观察.
但是,native除了实现中的这些示例之外,我还没有找到任何何时何地使用的文档.任何帮助将不胜感激.
我正在尝试使用 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);
Run Code Online (Sandbox Code Playgroud)
我尝试了很多方法,但似乎无法完全正确。
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);
Run Code Online (Sandbox Code Playgroud)
如何正确创建 foo 类的对象并设置它们的值,以及如何制作适合传递的数组?
我正在尝试从 包装read函数unistd.h,但无法让它工作。下面是我有:(文件:read.raku)
use NativeCall;
# ssize_t read(int fd, void *buf, size_t count);
sub c_read(int32 $fd, Pointer $buf is rw, size_t $count --> ssize_t) is native is symbol('read') { * }
my $buf = Buf[byte].new(0 xx 5);
my $pbuf = nativecast(Pointer, $buf);
say c_read(3, $pbuf, 5);
say '---------------------';
say $buf;
Run Code Online (Sandbox Code Playgroud)
我像这样从命令行(bash)测试它:
use NativeCall;
# ssize_t read(int fd, void *buf, size_t count);
sub c_read(int32 $fd, Pointer $buf is rw, size_t $count --> ssize_t) is native is …Run Code Online (Sandbox Code Playgroud)