从 Cython 中的自定义 C++ 库键入?

Type from a custom C++ library within Cython?

我正在通过 Cython 包装一些代码。可以找到 C++ 实现 palisade-python-demo ckks_wrapper.h。目前,我专注于包装 class CiphertextInterfaceType,为方便起见复制在下面。

#include <palisade.h>

namespace pycrypto {

/*
 * Ciphertext python wrapper
 */
class CiphertextInterfaceType {
 public:
  /**
   * Default constructor
   */
  CiphertextInterfaceType();

  /**
   * Constructor from Ciphertext
   */
  CiphertextInterfaceType(lbcrypto::Ciphertext<lbcrypto::DCRTPoly> ciphertext);

  /**
   * Destructor
   */
  ~CiphertextInterfaceType();

  const lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly> &GetCiphertext() const;

 private:
  lbcrypto::Ciphertext<lbcrypto::DCRTPoly> m_ciphertext;
};
}

我面临的问题是我不知道如何“包装”或使用 lbcrypto::CiphertextImpl<lbcrypto::DCRTPoly>,我简称为 cipherTypecipherType 是来自不在标准中的外部库的自定义类型。我需要 1) 将其声明为私有变量,2) 创建一个接受它的构造函数,以及 3) 实现一个 getter.


下面是我的 .pxd 文件,(cython “header” 等价?)

cdef extern from "ckks_wrapper.cpp":
    pass

cdef extern from "ckks_wrapper.h" namespace "pycrypto":
    cdef cppclass CiphertextInterfaceType:
        ####################################
        # Attrs
        ####################################
        # TODO: define the private variable m_ciphertext from above

        ####################################
        # Constructors/ destructors
        ####################################
        CiphertextInterfaceType() except +

        # TODO: the constructor below is supposed to accept an 
        CiphertextInterfaceType() except +

        ####################################
        # Methods
        ####################################
        # TODO:
            # Implement the *GetCiphertext

所以,我已经完成了关于包装一些 Rectangle class、Cython - wrapping Rectangle 的 cython 教程,这很有帮助,但我显然遗漏了一些东西。如何在我的 .pxd 文件中“定义”类型 cipherType


跟进 DavidW

  1. 了解“链接”

所以,我的 ckks_wrapper.hpp 有一个命名空间 pycrypto。在 ckks_wrapper.hpp 中,我还 include <palisade.h> 本身具有命名空间 lbcrypto。根据答案,这是否意味着我可以直接访问库 palisade.hlbcrypto 的命名空间,Cython 编译器会知道在 palisade.h 中查找?

我只是想确定我是否理解

  1. 了解代码。

关于在哪里定义CiphertextDCRTPoly "Ciphertext<DCRTPoly>"

cdef extern from "ckks_wrapper.cpp":
    pass

cdef extern from "ckks_wrapper.hpp" namespace "libcrypto":
    cdef cppclass CiphertextDCRTPoly "Ciphertext<DCRTPoly>":
        pass


cdef extern from "ckks_wrapper.h" namespace "pycrypto":
    cdef cppclass CiphertextInterfaceType:
        ...

cdef extern from "ckks_wrapper.cpp":
    pass

cdef extern from "ckks_wrapper.h" namespace "pycrypto":
    cdef extern from "ckks_wrapper.hpp" namespace "libcrypto":
        cdef cppclass CiphertextDCRTPoly "Ciphertext<DCRTPoly>":
            pass
    cdef cppclass CiphertextInterfaceType:
        ...
        CiphertextInterfaceType(CiphertextDCRTPoly) except +
        ...

我倾向于第二种,因为如果不是,我不知道如何在 CiphertextInterfaceType

中使用“CiphertextDCRTPoly”

首先,您不需要将其声明为私有变量。没有办法做到这一点,也没有这样做的目的。回应您在评论中的建议,您可以使用类似于 Python 的双下划线 (__x):Cython 无法生成可以访问私有变量的 C++ 代码,因此没有任何价值在这

作为一般规则,Cython 只需要知道您想要访问的 public 接口部分。因此,如果您不需要其他功能,您也可以愉快地省略它们。不过,我会假设你这样做。

Cython 确实有 some understanding of C++ templates 使用方括号。这里有一些限制,但您可以涵盖大部分代码:

cdef extern from "somewhere.hpp" namespace "libcrypto":
   cdef cppclass Ciphertext[T]
       pass

   cdef cppclass DCRTPoly:
       pass

然后,您可以使用 CiphertextInterfaceType[DCRTPoly] 作为参数声明构造函数和函数。

或者,您可以跳过使用模板,只使用 Cython 的 "cname" feature,在其中您将 Cython 包装器命名为一件事,但在生成代码时为其提供一个替代名称:

cdef extern from "something.hpp" namespace "libcrypto":
    cdef cppclass CiphertextDCRTPoly "Ciphertext<DCRTPoly>":
        pass

如果 Ciphertext<DCRTPoly> 是您计划使用的唯一版本的模板,这可能有意义。