我正在尝试实现一个包装器,用于对公钥运行费马分解测试。我已经使用 SWIG 成功生成了共享库:
fermat.h
:
#ifndef FERMAT_H
#define FERMAT_H
#include <iostream>
#include <stdio.h>
#include <gmpxx.h>
class Fermat
{
private:
mpz_class key;
mpz_class ceil_sqrt(const mpz_class&);
public:
Fermat(mpz_class);
std::string test();
};
#endif
fermat.cpp
:
#include "fermat.h"
#include <iostream>
#include <sstream>
#include <gmpxx.h>
Fermat::Fermat(mpz_class n)
{
key = n;
}
std::string Fermat::test()
{
// Test logic. Not important
}
mpz_class Fermat::ceil_sqrt(const mpz_class& n)
{
// A helper function
}
我使用以下 Makefile 和 SWIG 所需的
.i
文件编译了此文件。
Makefile
:
all:
swig -c++ -python -v -I/usr/include/ fermat.i
python setup.py build_ext --inplace
g++ -O3 -fPIC -c -lgmp -lgmpxx fermat.cpp
g++ -O3 -fPIC -c -lgmp -lgmpxx -I/usr/include/python3.10 fermat_wrap.cxx
g++ -shared fermat.o fermat_wrap.o -lgmp -lgmpxx -o _fermat.so
fermat.i
:
%module fermat
%{
#define SWIG_FERMAT_WITH_INIT
#include "fermat.h"
%}
%include "std_string.i"
%include "fermat.h"
现在,我可以将此 SWIG 模块包含在调用此测试方法的
main.py
代码中。我将公钥的 e 值作为十进制数传递给构造函数。
import fermat as f
key_decimal = 98372489374731875343284493738234 # arbitrarily long decimal number
test_fermat = f.Fermat(key_decimal)
print(test_fermat.test())
总而言之:我试图将 Python 中的整数传递给接受
mpz_class
类型参数的构造函数。据我所知,没有本地方法可以将 int 转换为 mpz_class
,因此这使得我的 SWIG 模块毫无用处,除非我找到一种方法让构造函数在 Python 中接受这个大整数。
运行上述 Python 代码将导致
TypeError: in method 'new_Fermat', argument 1 of type 'mpz_class'
我读过关于 SWIG 中的 typemaps ,这可能会派上用场,但我不确定它们是否能解决我的问题。我想我应该先在这里寻求安慰。
编辑:作为创可贴修复,我重写了构造函数以接受
std::string
-s 并将密钥作为字符串传递。
Fermat::Fermat(std::string n)
{
mpz_set_str(key.get_mpz_t(), n.c_str(), 10);
}
test_fermat = f.Fermat(str(key_decimal))
factors_string = test_fermat.test()
近似值,未测试:
%typemap(in) mpz_class & {
char *cstr;
Py_ssize_t len;
if (PyUnicode_Check(obj)) {
if (PyBytes_AsStringAndSize($1, &cstr, &len) == -1)
return SWIG_TypeError;
cstr = (char *)SWIG_PyUnicode_AsUTF8AndSize($1, &len, &bytes);
$1 = new mpz_class(cstr);
} else {
%argument_fail(res, "must be string", $symname, $argnum);
}
}