Sum*_*nal 5 c rakudo nativecall raku
我想从 Raku 调用 C 函数https://github.com/wch/r-source/blob/trunk/src/nmath/rmultinom.c#L47。\n为此,我将 Raku 函数定义为
\nuse NativeCall;\nconstant RMATH = "./Rmath.dll";\nmulti set_seed(uint32, uint32)\n is native( RMATH ) { * };\nmulti set_seed(UInt() $a, UInt() $b) is export {\n set_seed(my uint32 $ = $a, my uint32 $ = $b)\n}\nsub rmultinom(int32, CArray[num64], int32, CArray[int32])\n is native( RMATH ) { * }; \n\nsub raku_rmultinom($n , $size, @prob is copy) is export {\n @prob = @prob.map: {$_.Num};\n my $prob = CArray[num64].new(@prob);\n my $ints = CArray[int32].allocate($size);\n rmultinom($n, $prob, $size, $ints);\n return $ints.list\n}\nRun Code Online (Sandbox Code Playgroud)\n一个电话
\nmy @prob = [0.1, 0.3, 0.5, 0.1];\nset_seed(123,456);\nsay raku_rmultinom(100, 5, @prob);\nRun Code Online (Sandbox Code Playgroud)\n给出
\n(9 29 49 13 0)\nRun Code Online (Sandbox Code Playgroud)\n符合C代码:
\nuse NativeCall;\nconstant RMATH = "./Rmath.dll";\nmulti set_seed(uint32, uint32)\n is native( RMATH ) { * };\nmulti set_seed(UInt() $a, UInt() $b) is export {\n set_seed(my uint32 $ = $a, my uint32 $ = $b)\n}\nsub rmultinom(int32, CArray[num64], int32, CArray[int32])\n is native( RMATH ) { * }; \n\nsub raku_rmultinom($n , $size, @prob is copy) is export {\n @prob = @prob.map: {$_.Num};\n my $prob = CArray[num64].new(@prob);\n my $ints = CArray[int32].allocate($size);\n rmultinom($n, $prob, $size, $ints);\n return $ints.list\n}\nRun Code Online (Sandbox Code Playgroud)\nmy @prob = [0.1, 0.3, 0.5, 0.1];\nset_seed(123,456);\nsay raku_rmultinom(100, 5, @prob);\nRun Code Online (Sandbox Code Playgroud)\n但是当我将大小增加到时10,请参见下面的示例,输出看起来很奇怪:
(9 29 49 13 0)\nRun Code Online (Sandbox Code Playgroud)\n(0 0 0 0 0 -1 0 0 0 0) # expectation was (9 29 49 13 0 0 0 0 0 0)\nRun Code Online (Sandbox Code Playgroud)\n在 C 中时:
\n#define MATHLIB_STANDALONE 1\n#include "Rmath.h"\n#include <stdio.h>\n\nint main(int argc, char** argv) {\n int draws = 100;\n int classes = 5;\n int vals[classes];\n double probs[4] = {0.1, 0.3, 0.5, 0.1};\n\n set_seed(123, 456);\n rmultinom(draws, probs, classes, vals);\n\n for(int j=0; j < classes; j++) {\n printf("Count of class %i drawn: %i\\n", j, vals[j]);\n }\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\nCount of class 0 drawn: 9\nCount of class 1 drawn: 29\nCount of class 2 drawn: 49\nCount of class 3 drawn: 13\nCount of class 4 drawn: 0\nRun Code Online (Sandbox Code Playgroud)\n我的 Raku 代码中的实现有什么问题吗raku_rmultinom?
系统信息: \n这是在 Windows 10 64 位中完成的。为了重现性,我在这里提供了标头和动态库:\n https://replit.com/@sumankhanal/rakunativecall。
\n要使用同一文件夹中的 Rmath.h 头文件和库来测试 C 文件,请移至该目录并从cmd以下行运行:
gcc -I. -L. <cfile> -lRmath\n.\\a.exe\nRun Code Online (Sandbox Code Playgroud)\n否则,我是这个包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\xe2\x84\xa2 v2023.09.\nImplementing the Raku\xc2\xae Programming Language v6.d.\nBuilt on MoarVM version 2023.09.\nRun Code Online (Sandbox Code Playgroud)\n
我认为有必要总结一下这个 SO 中发生的事情。
首先,@Suman(提问者)得出的结论(在他们的问题下面的评论中)是答案“看起来像”:
@prob.append(0 xx $size - @prob)
Run Code Online (Sandbox Code Playgroud)
这反映了这样一个事实:对于这个 Q,有时会出现弥合 C 和 Raku 之间差距的情况,问题是 Raku 规范(在 Raku 中编码时通常有意义)和 C 规范(在用 Raku 编码时通常有意义)之间不匹配。 C)而不是双方技术的问题。评论交流中的一些摘录说明了深入了解这种不匹配的过程:
在 Ubuntu 上测试...输出如下:
(9 29 49 13 0 0 0 0 0 0)
Raku 是动态语言,C 是静态语言。您需要非常小心数组大小。没有问题,
4因为它正是数组的大小@prob。
在 Raku 部分,当 时
$size > +@prob,您正在调用未定义的行为...补救措施可能是确保@prob有足够的带有0s 填充的元素,例如,通过@prob.append(0 xx $size - @prob);inraku_rmultinom。
在C中,当你声明一个变量但没有初始化它时,它将被赋予一个“垃圾”值,即,无论值恰好位于指定给该变量的内存地址处。对于数组,它的所有元素都将具有谁知道什么值,例如您观察到的
1635326112或32758或0。另一方面,在 Rakudo 的 NativeCall 中,该.allocate方法恰好用0s 显式初始化数组元素,因此您拥有所有0s (除了 s-1)。
| 归档时间: |
|
| 查看次数: |
203 次 |
| 最近记录: |