SWIG、Python-C++ 和 GMP – 将 int 类型参数传递给 SWIG 生成的共享库中接受 mpz_class 类型参数的函数

问题描述 投票:0回答:1

我正在尝试实现一个包装器,用于对公钥运行费马分解测试。我已经使用 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()
python c++ swig gmp
1个回答
0
投票

近似值,未测试:

%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);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.