我想从Raku调用一个C函数https://github.com/wch/r-source/blob/trunk/src/nmath/rmultinom.c#L47。为此,我将Raku函数定义为
use NativeCall;
constant RMATH = "./Rmath.dll";
multi set_seed(uint32, uint32)
is native( RMATH ) { * };
multi set_seed(UInt() $a, UInt() $b) is export {
set_seed(my uint32 $ = $a, my uint32 $ = $b)
}
sub rmultinom(int32, CArray[num64], int32, CArray[int32])
is native( RMATH ) { * };
sub raku_rmultinom($n , $size, @prob is copy) is export {
@prob = @prob.map: {$_.Num};
my $prob = CArray[num64].new(@prob);
my $ints = CArray[int32].allocate($size);
rmultinom($n, $prob, $size, $ints);
return $ints.list
}
字符串
电话
my @prob = [0.1, 0.3, 0.5, 0.1];
set_seed(123,456);
say raku_rmultinom(100, 5, @prob);
型
给
(9 29 49 13 0)
型
- 符合 * C代码:
#define MATHLIB_STANDALONE 1
#include "Rmath.h"
#include <stdio.h>
int main(int argc, char** argv) {
int draws = 100;
int classes = 5;
int vals[classes];
double probs[4] = {0.1, 0.3, 0.5, 0.1};
set_seed(123, 456);
rmultinom(draws, probs, classes, vals);
for(int j=0; j < classes; j++) {
printf("Count of class %i drawn: %i\n", j, vals[j]);
}
return 0;
}
Count of class 0 drawn: 9
Count of class 1 drawn: 29
Count of class 2 drawn: 49
Count of class 3 drawn: 13
Count of class 4 drawn: 0
但是当我将大小增加到10
时,请参见下面的示例,输出似乎很奇怪:
my @prob = [0.1, 0.3, 0.5, 0.1];
set_seed(123,456);
say raku_rmultinom(100, 10, @prob);
(0 0 0 0 0 -1 0 0 0 0) # expectation was (9 29 49 13 0 0 0 0 0 0)
的字符串
在C中:
int main(int argc, char** argv) {
int draws = 100;
int classes = 10;
int vals[classes];
double probs[4] = {0.1, 0.3, 0.5, 0.1};
set_seed(123, 456);
rmultinom(draws, probs, classes, vals);
for(int j=0; j < classes; j++) {
printf("Count of class %i drawn: %i\n", j, vals[j]);
}
return 0;
}
Count of class 0 drawn: 9
Count of class 1 drawn: 29
Count of class 2 drawn: 49
Count of class 3 drawn: 13
Count of class 4 drawn: 0
Count of class 5 drawn: 0
Count of class 6 drawn: 0
Count of class 7 drawn: 0
Count of class 8 drawn: 0
Count of class 9 drawn: 0
在我的Raku代码中实现raku_rmultinom
有问题吗?
**系统信息:**这是在Windows 10 64位中完成的。为了重现性,我在这里提供了头部和动态库:https://replit.com/@sumankhanal/rakunativecall。
要在同一个文件夹中测试带有Rmath. h头和库的C文件,请移动到该目录并从cmd
行运行:
gcc -I. -L. <cfile> -lRmath
.\a.exe
型
否则,我是这个软件包https://github.com/sumanstats/Statistics的作者,该软件包在全球范围内提供raku_rmultinom
,任何人都可以安装和测试输出及其行为。
使用的Raku版本是从https://rakudo.org/dl/rakudo/rakudo-moar-2023.09-01-win-x86_64-msvc.zip;raku -v
下载的,提供:
Welcome to Rakudo™ v2023.09.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2023.09.
型
1条答案
按热度按时间zyfwsgd61#
我认为这是值得总结的事情发生在这样。
首先,@Suman(提问者)的结论(在他们问题下面的评论中)是答案“看起来像”什么:
字符串
这反映了这样一个事实,即对于这个Q,有时在桥接C和Raku之间的差距时就是这种情况,问题在于,(在Raku中编码时通常是有意义的)和C规范(通常在C中编码时有意义)而不是任何一方的技术问题。评论交流中的一些摘录说明了深入了解这一问题的过程。不匹配:
在Ubuntu上测试.输出如预期:
(9 29 49 13 0 0 0 0 0 0)
Raku是一种动态语言,C是静态的。你需要非常小心数组的大小。
4
没有问题,因为它正好是@prob
数组的大小。在Raku部分,当
$size > +@prob
时,您正在调用未定义的行为.在C中,当你声明一个变量但没有初始化它时,它将被赋予一个“垃圾”值,即,任何碰巧位于指定给变量的内存地址的值。对于数组,它的所有元素都将具有谁知道的值,如
1635326112
或32758
或0
。另一方面,在Rakudo的NativeCall中,.allocate
方法恰好用0
s显式地初始化数组元素,所以你有所有的0
s(除了那个-1
)。