将C对象数组包装到C ++类中

时间:2018-02-03 21:12:47

标签: c++ c++11

我的library(shiny) library(shinydashboard) ui <- dashboardPage( dashboardHeader(), dashboardSidebar(), dashboardBody( tags$style(HTML(" .box.box-solid.box-primary>.box-header { } .box.box-solid.box-primary{ background:#222d32 } ")), fluidRow( box(width = 6, title = "test", status = "primary", solidHeader = TRUE, "Box content" ) ) ) ) server <- function(input, output) {} shinyApp(ui, server) 库有这样的API:

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    tags$style(HTML("

                    .box.box-solid.box-primary>.box-header {
                    color:#fff;
                    background:#222d32
                    }

                    .box.box-solid.box-primary{
                    border-bottom-color:#222d32;
                    border-left-color:#222d32;
                    border-right-color:#222d32;
                    border-top-color:#222d32;
                    background:#222d32
                    }

                    ")),
    fluidRow(
      box(width = 6, title = "test", status = "primary", solidHeader = 
        TRUE,
         "Box content"
      )
    )
    )
  )


server <- function(input, output) {}

shinyApp(ui, server)

为了简化它的用法,我用这样的方式包装它:

C

一切都很好,但是我必须包装这些不透明物体的数组:

extern "C" {
    typedef struct Opaque Opaque;

    Opaque *foo_new();
    void foo_delete(Opaque *);
    int foo_f(Opaque *, int);
}

所以我需要实现class Foo final { public: Foo() { self_ = foo_new(); } ~Foo() { foo_delete(self_); } //code for copy/move constructor and operator= int f(int a) { return foo_f(self_, a); } private: Opaque *self_; };

extern "C" {
    typedef struct OpaqueArray OpaqueArray;

    OpaqueArray *calc_foo_array();
    void foo_array_delete(OpaqueArray *);
    Opaque *foo_array_elem(OpaqueArray *, size_t i);
}

但是我应该归结为class FooArray

的结果

我可以从class FooArray final { public: ??? operator[](const size_t i) { auto obj = foo_array_elem(self_, i); ??? } private: OpaqueArray *self_; }; 创建operator[],但Foo是免费的数组部分, 怎么了。我可以创建与Opaque *完全相同的Foo::~Foo(), 但不要拨打FooRef,但实际上我有几个Foo, 我更喜欢不创建这么多代码重复。 可能我可以某种方式使用foo_delete,因为C classes并从reinterpret_cast返回sizeof(Foo) = sizeof(Opaque *),但Foo &实际上是operator[], 所以我需要在某处按住Foo &以使其稳定。

对于这类问题,可能有一些标准解决方案吗?

2 个答案:

答案 0 :(得分:4)

你可以修改你的Foo类,使它可以保存一个它不拥有的指针。

class Foo
{
    public:
        Foo()
        {
            self_ = foo_new();
            m_owned = true;
        }

        Foo(Opaque *pOpaque) 
        { 
            self_ = foo_new(); 
            m_owned = false;
        }

        ~Foo()
        {
            if (m_owned) foo_delete(self_);
        }

        //code for copy/move constructor and operator=
        int f(int a) { return foo_f(self_, a); }

    private:
        bool m_owned;
        Opaque *self_;
};


class FooArray
{
    public:
        Foo operator[](const size_t i)
        {
           return Foo(foo_array_elem(self_, i));
        }

    private:
        OpaqueArray *self_;
};

答案 1 :(得分:2)

我是按照你FooRef提出的方式做的,但有点不同:

class FooRef {
public:
    FooRef (Opaque *o) { self_ = o; }
    int f(int a) { return foo_f(self_, a); }
protected:
    Opaque *self_;
};


class Foo : public FooRef {
public:
    Foo() { self_ = foo_new(); }
    //code for copy/move constructor and operator=
    ~Foo () { foo_delete(self_); }
};

此解决方案避免了代码重复,并允许您安全地从数组返回Foo。顺便说一下,你有机制从FooRef简单地创建Foo。现在你可以做到:

class FooArray final {
public:
    FooRef operator[](const size_t i) {
       return FooRef(foo_array_elem(self_, i));
    }
private:
    OpaqueArray *self_;
};

我认为这应该以优雅的方式完成。