在回调中将指针转换为向量类型

时间:2018-11-11 13:19:57

标签: c++ lua

周末程序员,C ++的新手,正在与指针之战作战!

我正在尝试使用C ++编写一种方法,该方法使用通过void *参数传递给回调函数的向量从API检索数据。

返回的数据将被传递回lua,后者是应用程序中使用的前端。 lua并不是让我感到困惑的地方,这是使我的结构中充满来自回调的数据的挑战。

我已经使用简单的int指针完成了所有工作,但是被告知使用结构的首选方法,建议我执行以下操作:

1 - define a struct that contains the 6 ints
2 - create an std::vector that can contain instances of the new struct
3 - pass a pointer to the vector as refcon into XPLMGetAllMonitorBoundsGlobal
inside the callback function:
    4 - cast the refcon pointer back to the vector type
    5 - create a new instance of the struct and fill it with the 6 ints that are passed to the callback function
    6 - push that instance into the vector
7 - when XPLMGetAllMonitorBoundsGlobal returns, the vector will be filled with the bounds of all screens
8 - convert the vector into a lua-compatible thing, probably a two-dimensional array
push that array into lua

这是我想出的代码,为此做了很多Google / Stackoverflow搜索,但是即使代码编译了,它还是会挂起应用程序或导致段错误,这取决于我所调整的内容。我认为主要的问题是如何将refcon指针转换回向量类型,指针的引用/取消引用过多,并且可能还有其他问题。

struct  MonitorBoundsStructure    // #1
{
    int     MonitorIndex;
    int     LeftBx;
    int     TopBx;
    int     RightBx;
    int     BottomBx;
    int     RefCon;
};

static void LuaReceiveMonitorBoundsOS_t(int inMonitorIndex, int inLeftBx, int inTopBx, int inRightBx, int inBottomBx, void * refcon)
{
    vector<MonitorBoundsStructure*>& MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure*> *>(refcon);  #4
    //vector<MonitorBoundsStructure> MonitorBounds = reinterpret_cast<vector<MonitorBoundsStructure*> *>(refcon);
    //vector<MonitorBoundsStructure> MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure> *>(refcon);
    //vector<MonitorBoundsStructure> MonitorBounds = reinterpret_cast<vector<MonitorBoundsStructure> *>(refcon);
    //vector<MonitorBoundsStructure>* MonitorBounds = static_cast<vector<MonitorBoundsStructure> *>(refcon);

    MonitorBoundsStructure returnData; //{0,0,0,0,0,0};   #5
    returnData.MonitorIndex = inMonitorIndex;
    returnData.LeftBx = inLeftBx;
    returnData.TopBx = inTopBx;
    returnData.RightBx = inRightBx;
    returnData.BottomBx = inBottomBx;
    returnData.RefCon = *(int *)refcon;

    MonitorBounds.push_back(&returnData);   // #6
}

static int LuaXPLMGetAllMonitorBoundsOSTest()
{
    //std::vector<std::shared_ptr<MonitorBoundsStructure>> MonitorBounds;
    vector<MonitorBoundsStructure> MonitorBounds;  // #2

    XPLMGetAllMonitorBoundsOS(LuaReceiveMonitorBoundsOS_t, &MonitorBounds);  // #3

    int i = 0;
    for (vector<MonitorBoundsStructure>::iterator it = MonitorBounds.begin(); it != MonitorBounds.end(); ++it)
    {
        i++;
        logMsg(logToAll, string("MonitorBounds ").append(to_string(i)));

    }

    return 1;
}

如果我注释掉MonitorBounds.push_back(&returnData),则代码至少会到达回调内部的结构填充有正确数据的位置,我碰到一堵墙,将该结构返回给调用函数,这意味着将void *强制转换为vector至少是错误的。

我在评论中留下了其他一些尝试,以展示我的尝试。

我是接近解决方案还是离开?

解决方案: 感谢Ted Lyngmo提供的解决方案,甚至可以在自己的系统上编写测试代码。我怀疑,我的问题在于指向向量的指针。我同时提供了push_back和emplace_back(我发现比较整洁)的答案。

-回调函数:

static void LuaReceiveMonitorBoundsOS_e(int inMonitorIndex, int inLeftBx, int inTopBx, int inRightBx, int inBottomBx, void * refcon)
{
    auto& MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure>*>(refcon);


    MonitorBoundsStructure returnData;
    returnData.MonitorIndex = inMonitorIndex;
    returnData.LeftBx = inLeftBx;
    returnData.TopBx = inTopBx;
    returnData.RightBx = inRightBx;
    returnData.BottomBx = inBottomBx;

    MonitorBounds.push_back(returnData);
}

static void LuaReceiveMonitorBoundsOS_e(int inMonitorIndex, int inLeftBx, int inTopBx, int inRightBx, int inBottomBx, void * refcon)
{
    auto& MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure>*>(refcon);

    MonitorBounds.emplace_back(
         MonitorBoundsStructure{
             inMonitorIndex,
             inLeftBx,
             inTopBx,
             inRightBx,
             inBottomBx
         }
     );
}

调用功能:

static int LuaXPLMGetAllMonitorBoundsOSTestE(lua_State *L)
{
    vector<MonitorBoundsStructure> MonitorBounds;

    XPLMGetAllMonitorBoundsOS(LuaReceiveMonitorBoundsOS_e, &MonitorBounds);

    for (auto& m : MonitorBounds) {
         std::cout << m.MonitorIndex << "\n";
     }

    return 1;
}

1 个答案:

答案 0 :(得分:2)

<!doctype html>
<html lang="fr">
<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
  <link rel="stylesheet" type="text/css" href="THC.css">

  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous">
  <link href="https://fonts.googleapis.com/css?family=Libre+Baskerville" rel="stylesheet">

  <title>Hello, world!</title>
</head>
<body>



  <!-- debut navbar -->

  <nav class="navbar  nav-down fixed-top  navbar-expand-lg navbar-dark bg-dark">
    <div class="container">
      <a class="navbar-brand" href="#">
        <img src="img/logo.png" width="40" height="40" class="d-inline-block align-top img-thumbnail" alt="logo">
      </a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarResponsive">
        <ul class="navbar-nav ml-auto">
          <li class="nav-item active">
            <a class="nav-link" href="index.html">Home
              <span class="sr-only">(current)</span>
            </a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#produit">Notre produit?</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#nous">A propos de nous</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#contact">Contact</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#footer"></a>
          </li>
        </ul>
      </div>
    </div>
  </nav>

  <!-- fin navbar -->

  <div class="container">

    <!-- debut Einstein -->
    <div class="card card-cascade wider">


      <div class="view view-cascade overlay">
        <img  class="card-img-top" src="https://mdbootstrap.com/img/Photos/Others/photo6.jpg" alt="Albert Einstein">
        <a href="#!">
          <div class="mask rgba-white-slight"></div>
        </a>
      </div>

      <!-- Card content -->
      <div class="card-body card-body-cascade text-center">

        <!-- Title -->
        <h4 class="card-title"><strong>Albert Einstein</strong></h4>
        <!-- Subtitle -->
        <!-- Text -->
        <p class="card-text"> “L’imagination est plus importante que le savoir.”</p>


      </div>

    </div>
    <!-- fin Einstein -->

    <hr>

    <!-- debut notre produit -->
    <div class="card card-cascade wider" >

      <!-- Title -->
      <h4 class="produit card-title"  id="produit"><strong>TURBO HAND CONTROL</strong></h4>

      <!-- Card image -->
      <div class="view view-cascade overlay">
        <img  class="card-img-top" src="img/main.jpg" alt="Produit">
        <a href="#!">
          <div class="mask rgba-white-slight"></div>
        </a>
      </div>

      <!-- Card content -->
      <div class="card-body card-body-cascade text-center">


        <!-- Subtitle -->
        <!-- Text -->
        <p class="card-text">L'idée de notre projet est une voiture télécommandée, controlée par un exosquelette main qui fonctionnerait en correspondance avec les mouvements(ex: pencher pour tourner, monter ou descendre pour accelerer).

          Concretement qu'est ce qui differencie notre produit de tout autre voiture télécommandée sur le marché?
          Tout simplement, avez-vous dèjà remarqué que toutes les voitures télécommandées sur le marché sont crée dèjà toutes faites et donc sans identité personnelle?
          Eh bien, notre but est de créer une voiture HI-TECH personnalisable sur l'entièrté de l'esthétique de la voiture, pour pouvoir plaire au goût de chacun. 
        Avec une utilisation simple, donc accessible aux plus petits, une capacité de gadgets avancé pour éviter l'ennuie des plus ageux(un mini bafle intégré dans la voiture relié à un micro sur l'exo pour pouvoir communiquer à distance, une caméra intègré à la voiture avec écrant sur l'exo pour l'utilisation à distance, plusieurs programmes d'utilisation comme la commande autonome, la commande par appli sur smartphone).</p>


      </div>

    </div>
    <!-- fin notre produit -->
    <hr>
    <!-- debut carroussel -->

    <div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">
      <ol class="carousel-indicators">
        <li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="3"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="4"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="5"></li>
      </ol>
      <div class="carousel-inner">

        <div class="carousel-item active">
          <div  class="embed-responsive embed-responsive-16by9">
            <iframe id="player" src="img/main.mp4" allowfullscreen></iframe>
          </div><!-- end .embed-responsive -->
          <div class="carousel-caption d-none d-md-block">
            <h4>Le projet initial</h4>
            <p>Un prototype de THC</p>
          </div>
        </div>

        <div class="carousel-item">
          <img class="d-block w-100" src="img/salle3.jpg" alt="salle">
          <div class="carousel-caption d-none d-md-block">
            <h4>La salle</h4>
            <p>Lieux de travail</p>
          </div>
        </div>

        <div class="carousel-item">
          <img class="d-block w-100" src="img/créateur1.jpg" alt="Othman et hamza">
          <div class="carousel-caption d-none d-md-block">
            <h4>Othman et Hamza</h4>
            <p>Jeunes entrepreneurs et créateurs de THC (Turbo Hand Control)</p>
          </div>
        </div>

        <div class="carousel-item">
          <img class="d-block w-100" src="img/piece1.jpg" alt="Pieces en plastique">
          <div class="carousel-caption d-none d-md-block">
            <h4>Pièces en plastique</h4>
            <p>Quelques pièces modélisées et imprimées grâce à l'imprimante 3D Ultramaker 2+</p>
          </div>
        </div>

        <div class="carousel-item">
          <img class="d-block w-100" src="img/turbo5.jpg" alt="voiture">
          <div class="carousel-caption d-none d-md-block">
            <h4>La voiture</h4>
            <p>La voiture commandée grâce a THC</p>
          </div>
        </div>
      </div>
      <a class="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
        <span class="sr-only">Previous</span>
      </a>
      <a class="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
        <span class="carousel-control-next-icon" aria-hidden="true"></span>
        <span class="sr-only">Next</span>
      </a>
    </div>

    <!-- fin carroussel -->

    <hr>

    <!-- Card Narrower -->
    <div class="card card-cascade narrower">

      <!-- Title -->
      <h4 class="produit card-title" id="nous"><strong>L'equipe T.H.C.</strong></h4>

      <!-- Card image -->
      <div class="view view-cascade overlay">
        <img  class="card-img-top" src="img/créateur1.jpg" alt="Othman et Hamza">
        <a>
          <div class="mask rgba-white-slight"></div>
        </a>
      </div>

      <!-- Card content -->
      <div class="card-body card-body-cascade">

        <!-- Title -->
        <h4 class="font-weight-bold card-title">Othman</h4>
        <!-- Text -->
        <p class="card-text">

          Née en Belgique,le 21 juillet 1999 et  originaire du Maroc Othman est un jeune entrepreuneur de bientôt 20 ans passionner par les innovations et les nouvelles technologie et qui aime faire parler sa créativité. C'est dans cette optique qu'il s'est lancé dans se projet qui lui correspond , dont il est le fondateur, innovateur, fabricant et s'occupe du marketing en partenariat avec son acolyte Hamza.  

          <h4 class="font-weight-bold card-title">Hamza</h4>

          hamza, originaire de la tchétchènie, était un jeune étudiant jusqu'au jour où il a décidé d'arrêté ses études pour se diriger vers passion, la programation des objets 3D.
          A l'aide de son camarade Othman, les deux jeunes hommes ont pu créé un site web et vendre de leurs produits High-tech.


        </p>
        <!-- Button -->

      </div>

    </div>
    <!-- Card Narrower -->

    <hr>

    <!-- Card Regular -->
    <div class="card card-cascade">

      <h4 class="card-title"><strong>Ultimaker 2+</strong></h4>

      <!-- Card image -->
      <div class="view view-cascade overlay">
        <img class="card-img-top" src="img/um.jpg" alt="imprimante 3D">
        <a>
          <div class="mask rgba-white-slight"></div>
        </a>
      </div>

      <!-- Card content -->
      <div class="card-body card-body-cascade text-center">

        <!-- Title -->
        <h4 class="font-weight-bold card-title">L'imprimante 3d utilisée pour la création d'objets</h4>

        <!-- Text -->
        <p class="card-text">

          L'Ultimaker 2+ est la nouvelle version de l'imprimante 3D Ultimaker 2. Présentée à l'occasion du CES Las Vegas 2016, elle fait partie des références de l'impression 3D personnelle. Les dimensions du modèle restent sensiblement les mêmes (350x350x400 mm) que sa grande soeur, l'Ultimaker Original, avec un volume d’impression légèrement plus grand à 230x225x205 mm VS 210x210x220 mm. Au niveau du design, on notera le travail effectué sur le chassis minimaliste en aluminium gris clair, non sans rappeler la marque à la pomme. L’Ultimaker est quasi-silencieuse, avec seulement 49 décibels émis. La vitesse d’impression atteind 300 mm/s pour une qualité maximale de 20 microns. Enfin, l’imprimante possède un plateau chauffant.
        </p>

      </div>

    </div>
    <!-- Card Regular -->

    <!-- fin cards -->
    <hr>
  </div>




  <!-- Optional JavaScript -->

  <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
  <script src="cht.js" crossorigin="anonymous"></script>
</body>
</html>

此后,returnData超出范围并被销毁。您现在在MonitorBounds中拥有的指针无效。

您似乎也正在转换为错误的类型。如果这是向量:

MonitorBoundsStructure returnData; //{0,0,0,0,0,0};   #5
MonitorBounds.push_back(&returnData);   // #6

您应该在回调中对此进行强制转换:

vector<MonitorBoundsStructure> MonitorBounds;

并推送整个结构,而不是指向它的指针:

auto& MonitorBounds = *reinterpret_cast<vector<MonitorBoundsStructure>*>(refcon);

编辑:我用自己的MonitorBounds.push_back(returnData); 制作了一个测试版本,以检查它是否正常工作,并且看起来还可以。

XPLMGetAllMonitorBoundsOS

输出

#include <iostream>
#include <string>
#include <vector>

typedef void (*XPLMReceiveMonitorBoundsOS_f)( int   inMonitorIndex,
                                              int   inLeftPx,
                                              int   inTopPx,
                                              int   inRightPx,
                                              int   inBottomPx,
                                              void* inRefcon);

struct  MonitorBoundsStructure    // #1
{
    int     MonitorIndex;
    int     LeftBx;
    int     TopBx;
    int     RightBx;
    int     BottomBx;
};

static void LuaReceiveMonitorBoundsOS_t(int inMonitorIndex, int inLeftBx, int inTopBx,
                                        int inRightBx, int inBottomBx, void* refcon)
{
    auto& MonitorBounds = *reinterpret_cast<std::vector<MonitorBoundsStructure>*>(refcon);

    MonitorBounds.emplace_back(
        MonitorBoundsStructure{
            inMonitorIndex,
            inLeftBx,
            inTopBx,
            inRightBx,
            inBottomBx
        }
    );
}

void XPLMGetAllMonitorBoundsOS(XPLMReceiveMonitorBoundsOS_f callback, void* inRefcon)
{
    callback(0,100,0,100,100, inRefcon);
    callback(1,99,1,99,99, inRefcon);
    callback(2,100,1,100,100, inRefcon);
}

static int LuaXPLMGetAllMonitorBoundsOSTest() {
    std::vector<MonitorBoundsStructure> MonitorBounds;  // #2

    XPLMGetAllMonitorBoundsOS(LuaReceiveMonitorBoundsOS_t, &MonitorBounds);  // #3

    for (auto& m : MonitorBounds) {
        std::cout << m.MonitorIndex << "\n";
    }

    return 1;
}

int main() {
    LuaXPLMGetAllMonitorBoundsOSTest();
}