perl xs 模块编写 - 使用同一个 xs 文件中的另一个函数
perl xs module writing - Use another function from within same xs file
我是 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,nColsMatrix,nRowsMatrix)];
n++;
}
RETVAL = 1;
return RETVAL;
OUTPUT:
RETVAL
然后我 运行 make
并通过编译过程,我在 undefined reference to 'matrixIndex'
的链接阶段出现错误。
所以我想知道从同一个 XS 文件中调用函数的标准 XS 方法是什么?
XS 代码创建 Perl 子程序。所以调用 XS 函数与 calling 任何其他 Perl 子函数相同。
与其处理这种复杂性和低效率问题,不如创建一个 C 函数而不是 Perl 子函数。 (如果需要,您可以使用 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, fromMatrix, nColsMatrix, nRowsMatrix, intoVector, 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, x, nColsMatrix, nRowsMatrix)];
n++;
}
RETVAL = 1;
}
OUTPUT:
RETVAL
您对 return
的使用不正确。如果您想过早 return,请使用 XSRETURN*
宏之一。
fromMatrix[...]
和intoVector[...]
是完全错误的。 fromMatrix
和 intoVector
是 C 数组。 (它们甚至不是 Perl 数组,这无关紧要。)
Perl 整数的大小为 IV
(或 UV
表示无符号),不一定 size_t
。使用它们以获得最佳兼容性。
如果你想要可移植性,你不能假定C99,所以你不能混合声明和代码。您需要在 PREINIT
中放置声明(或在 CODE
中使用卷曲来为变量声明创建新的范围)。
XSUB 不是 C 函数。 XS 预处理器确实根据您的声明创建了一个 C 函数,但它具有签名 void (CV*)
。然后,XSUB 从 Perl 参数堆栈中获取参数,并使用您的类型映射将它们转换为 C 值。因此无法直接调用您的 XSUB。
相反,您必须像调用任何其他 Perl 函数一样调用 XSUB,即将参数作为 SV*
s 压入堆栈。有关详细信息,请参阅 perldoc perlcall
。显然,这是乏味且低效的。
更好的解决方案是在您的 XS 文件中将您想要从 Perl 和 XS 使用的所有函数声明为 static
C 函数,然后编写 XS 胶水代码以将其公开给 Perl。这里:
static size_t matrixIndex(size_t colIndex, size_t rowIndex, size_t nCols, size_t nRows)
{
size_t register i; // unneeded
return (rowIndex * nCols) + colIndex;
}
请注意,如果此函数使用了 Perl API 的任何部分,那么您还应该使用 pTHX
和 aTHX
宏。声明更改为
static size_t matrixIndex(pTHX_ size_t colIndex, etc...) ...
当从 C 调用它时,你会写 matrixIndex(aTHX_ colIndex, etc...)
.
我是 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,nColsMatrix,nRowsMatrix)];
n++;
}
RETVAL = 1;
return RETVAL;
OUTPUT:
RETVAL
然后我 运行 make
并通过编译过程,我在 undefined reference to 'matrixIndex'
的链接阶段出现错误。
所以我想知道从同一个 XS 文件中调用函数的标准 XS 方法是什么?
XS 代码创建 Perl 子程序。所以调用 XS 函数与 calling 任何其他 Perl 子函数相同。
与其处理这种复杂性和低效率问题,不如创建一个 C 函数而不是 Perl 子函数。 (如果需要,您可以使用 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, fromMatrix, nColsMatrix, nRowsMatrix, intoVector, 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, x, nColsMatrix, nRowsMatrix)];
n++;
}
RETVAL = 1;
}
OUTPUT:
RETVAL
您对 return
的使用不正确。如果您想过早 return,请使用 XSRETURN*
宏之一。
fromMatrix[...]
和intoVector[...]
是完全错误的。 fromMatrix
和 intoVector
是 C 数组。 (它们甚至不是 Perl 数组,这无关紧要。)
Perl 整数的大小为 IV
(或 UV
表示无符号),不一定 size_t
。使用它们以获得最佳兼容性。
如果你想要可移植性,你不能假定C99,所以你不能混合声明和代码。您需要在 PREINIT
中放置声明(或在 CODE
中使用卷曲来为变量声明创建新的范围)。
XSUB 不是 C 函数。 XS 预处理器确实根据您的声明创建了一个 C 函数,但它具有签名 void (CV*)
。然后,XSUB 从 Perl 参数堆栈中获取参数,并使用您的类型映射将它们转换为 C 值。因此无法直接调用您的 XSUB。
相反,您必须像调用任何其他 Perl 函数一样调用 XSUB,即将参数作为 SV*
s 压入堆栈。有关详细信息,请参阅 perldoc perlcall
。显然,这是乏味且低效的。
更好的解决方案是在您的 XS 文件中将您想要从 Perl 和 XS 使用的所有函数声明为 static
C 函数,然后编写 XS 胶水代码以将其公开给 Perl。这里:
static size_t matrixIndex(size_t colIndex, size_t rowIndex, size_t nCols, size_t nRows)
{
size_t register i; // unneeded
return (rowIndex * nCols) + colIndex;
}
请注意,如果此函数使用了 Perl API 的任何部分,那么您还应该使用 pTHX
和 aTHX
宏。声明更改为
static size_t matrixIndex(pTHX_ size_t colIndex, etc...) ...
当从 C 调用它时,你会写 matrixIndex(aTHX_ colIndex, etc...)
.