我是XS的初学者,花了一些时间在网上寻找这个答案而没有运气.问题是XS更改了函数的名称,当它进行编译时,我将得到一个未定义的引用错误.例如,考虑下面的XS代码:
size_t matrixIndex (colIndex,rowIndex,nCols,nRows) size_t colIndex size_t rowIndex size_t nCols size_t nRows CODE: size_t register i; RETVAL = (rowIndex * nCols) + colIndex; OUTPUT: RETVAL
然后我尝试在下面这样的函数中使用它
int matrixCopyColumnVector_dbl (colIndex,fromMatrix,nColsMatrix,nRowsMatrix,intoVector,nRowsVector) size_t colIndex SV * fromMatrix size_t nColsMatrix size_t nRowsMatrix SV * intoVector size_t nRowsVector CODE: size_t register x,n; if( nRowsVector != nRowsMatrix) { RETVAL = 0; return RETVAL; } n = 0; for(x=0; x<= nRowsMatrix; x++) { intoVector[n] = fromMatrix[matrixIndex /*USE OF FUNCTION HERE!!*/(colIndex,x,nRowsMatrix)]; n++; } RETVAL = 1; return RETVAL; OUTPUT: RETVAL
解决方法
XS代码创建Perl subs.所以调用XS函数与
calling任何其他Perl子函数相同.
而不是处理这种复杂性和低效率,而不是创建一个C函数而不是Perl sub. (如果需要,可以使用XS独立公开该C函数.)
#define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" static UV matrixIndex(UV colIndex,UV rowIndex,UV nCols,UV nRows) { return (rowIndex * nCols) + colIndex; } MODULE = Foo::Bar PACKAGE = Foo::Bar int matrixCopyColumnVector_dbl(colIndex,nRowsVector) UV colIndex SV * fromMatrix UV nColsMatrix UV nRowsMatrix SV * intoVector UV nRowsVector PREINIT: UV register x,n; CODE: if (nRowsVector == nRowsMatrix) { RETVAL = 0; } else { n = 0; for (x=0; x<=nRowsMatrix; x++) { intoVector[n] = fromMatrix[matrixIndex(colIndex,nRowsMatrix)]; n++; } RETVAL = 1; } OUTPUT: RETVAL
您对退货的使用不正确.如果要提前返回,请使用其中一个XSRETURN *宏.
fromMatrix […]和intoVector […]是完全错误的. fromMatrix和intoVector是C数组. (它们甚至不是Perl数组,也不是相关的.)
Perl整数的大小为IV(或UV为unsigned),不一定是size_t.使用它们以获得最佳兼容性
如果你想要可移植性,你不能假设C99,所以你不能混合声明和代码.您需要在PREINIT中放置声明(或在CODE中使用curlies为变量声明创建新的作用域).