Search Unity

Plugin Initialization

Discussion in 'Scripting' started by Brad-Newman, Nov 22, 2014.

  1. Brad-Newman

    Brad-Newman

    Joined:
    Feb 7, 2013
    Posts:
    185
    I'm having trouble initializing a native plugin I'm writing and wondering if there is anything special you need to do when initializing plugins? I'm really new to this and don't really know C++ so it's quite possible I'm overlooking something obvious. I'm modifying C++ code that was originally written as an executable and was initialized with the function _tmain which read arguments from the command line. I commented out this function and created a new function called InitializePluginInternal and hard coded the arguments into the function. When I compile an executable and run it everything works fine, however when I compile a DLL and run InitializePlugin in Unity the app hangs and I have to kill it.

    Below is
    1. MotiveToUnityPlugin.cpp: excerpts showing the two initialization functions and the EXPORT_API functions for Unity.
    2. InitializeMotiveToUnityPlugin.cs: showing how I am calling the DLL functions.

    Here is a ZIP of the Visual Studio Community 2013 project and the Unity project if anyone wants to checkout the full source: https://drive.google.com/file/d/0B_5Y8udovIdbQVNLRlhGSTBPTFU/view?usp=sharing

    Thanks,
    Brad

    MotiveToUnityPlugin.cpp
    Code (CSharp):
    1.  
    2. //ORIGINAL INITIALIZATION CODE/////////////////////////////
    3. int _tmain(int argc, _TCHAR* argv[])
    4.  
    5. {
    6.  
    7.     tmainExcuted = true;
    8.     int iResult;
    9.     int iConnectionType = ConnectionType_Multicast;
    10.     //int iConnectionType = ConnectionType_Unicast;
    11.  
    12.     // parse command line args
    13.     if (argc > 1)
    14.     {
    15.         strcpy(szServerIPAddress, argv[1]);    // specified on command line
    16.         printf("Connecting to server at %s...\n", szServerIPAddress);
    17.     }
    18.     else
    19.     {
    20.         strcpy(szServerIPAddress, "");        // not specified - assume server is local machine
    21.         printf("Connecting to server at LocalMachine\n");
    22.     }
    23.     if (argc > 2)
    24.     {
    25.         strcpy(szMyIPAddress, argv[2]);        // specified on command line
    26.         printf("Connecting from %s...\n", szMyIPAddress);
    27.     }
    28.     else
    29.     {
    30.         strcpy(szMyIPAddress, "");          // not specified - assume server is local machine
    31.         printf("Connecting from LocalMachine...\n");
    32.     }
    33.  
    34.     // Create NatNet Client
    35.     iResult = CreateClient(iConnectionType);
    36.     if (iResult != ErrorCode_OK)
    37.     {
    38.         printf("Error initializing client.  See log for details.  Exiting");
    39.         return 1;
    40.     }
    41.     else
    42.     {
    43.         printf("Client initialized and ready.\n");
    44.     }
    45.  
    46.  
    47.     // send/receive test request
    48.     printf("[SampleClient] Sending Test Request\n");
    49.     void* response;
    50.     int nBytes;
    51.     iResult = theClient->SendMessageAndWait("TestRequest", &response, &nBytes);
    52.     if (iResult == ErrorCode_OK)
    53.     {
    54.         printf("[SampleClient] Received: %s", (char*)response);
    55.     }
    56.  
    57.     // Retrieve Data Descriptions from server
    58.     printf("\n\n[SampleClient] Requesting Data Descriptions...");
    59.     sDataDescriptions* pDataDefs = NULL;
    60.     int nBodies = theClient->GetDataDescriptions(&pDataDefs);
    61.     if (!pDataDefs)
    62.     {
    63.         printf("[SampleClient] Unable to retrieve Data Descriptions.");
    64.     }
    65.     else
    66.     {
    67.         printf("[SampleClient] Received %d Data Descriptions:\n", pDataDefs->nDataDescriptions);
    68.         for (int i = 0; i < pDataDefs->nDataDescriptions; i++)
    69.         {
    70.             printf("Data Description # %d (type=%d)\n", i, pDataDefs->arrDataDescriptions[i].type);
    71.             if (pDataDefs->arrDataDescriptions[i].type == Descriptor_MarkerSet)
    72.             {
    73.                 // MarkerSet
    74.                 sMarkerSetDescription* pMS = pDataDefs->arrDataDescriptions[i].Data.MarkerSetDescription;
    75.                 printf("MarkerSet Name : %s\n", pMS->szName);
    76.                 for (int i = 0; i < pMS->nMarkers; i++)
    77.                     printf("%s\n", pMS->szMarkerNames[i]);
    78.             }
    79.             else if (pDataDefs->arrDataDescriptions[i].type == Descriptor_RigidBody)
    80.             {
    81.                 //ORIGINAL CODE START
    82.  
    83.                 // RigidBody
    84.                 sRigidBodyDescription* pRB = pDataDefs->arrDataDescriptions[i].Data.RigidBodyDescription;
    85.                 printf("RigidBody Name : %s\n", pRB->szName);
    86.                 printf("RigidBody ID : %d\n", pRB->ID);
    87.                 printf("RigidBody Parent ID : %d\n", pRB->parentID);
    88.                 printf("Parent Offset : %3.2f,%3.2f,%3.2f\n", pRB->offsetx, pRB->offsety, pRB->offsetz);
    89.                 //ORIGINAL CODE END
    90.             }
    91.             else if (pDataDefs->arrDataDescriptions[i].type == Descriptor_Skeleton)
    92.             {
    93.                 // Skeleton
    94.                 sSkeletonDescription* pSK = pDataDefs->arrDataDescriptions[i].Data.SkeletonDescription;
    95.                 printf("Skeleton Name : %s\n", pSK->szName);
    96.                 printf("Skeleton ID : %d\n", pSK->skeletonID);
    97.                 printf("RigidBody (Bone) Count : %d\n", pSK->nRigidBodies);
    98.                 for (int j = 0; j < pSK->nRigidBodies; j++)
    99.                 {
    100.                     sRigidBodyDescription* pRB = &pSK->RigidBodies[j];
    101.                     printf("  Skeleton RigidBody Name : %s\n", pRB->szName);
    102.                     printf("  Skeleton RigidBody ID : %d\n", pRB->ID);
    103.                     printf("  Skeleton RigidBody Parent ID : %d\n", pRB->parentID);
    104.                     printf("  Parent Offset : %3.2f,%3.2f,%3.2f\n", pRB->offsetx, pRB->offsety, pRB->offsetz);
    105.  
    106.                     // populate bone name dictionary for use in xml ==--
    107.                     gBoneNames[pRB->ID] = pRB->szName;
    108.                 }
    109.             }
    110.             else
    111.             {
    112.                 printf("Unknown data type.");
    113.                 // Unknown
    114.             }
    115.         }
    116.     }
    117.  
    118.     // Ready to receive marker stream!
    119.     printf("\nClient is connected to server and listening for data...\n");
    120.     int c;
    121.     bool bExit = false;
    122.     while (c = _getch())
    123.     {
    124.         switch (c)
    125.         {
    126.         case 'q':
    127.             bExit = true;
    128.             break;
    129.         case 'r':
    130.             resetClient();
    131.             break;
    132.         case 'p':
    133.             sServerDescription ServerDescription;
    134.             memset(&ServerDescription, 0, sizeof(ServerDescription));
    135.             theClient->GetServerDescription(&ServerDescription);
    136.             if (!ServerDescription.HostPresent)
    137.             {
    138.                 printf("Unable to connect to server. Host not present. Exiting.");
    139.                 return 1;
    140.             }
    141.             break;
    142.         case 'f':
    143.         {
    144.             sFrameOfMocapData* pData = theClient->GetLastFrameOfData();
    145.             printf("Most Recent Frame: %d", pData->iFrame);
    146.         }
    147.         break;
    148.         case 'm':                            // change to multicast
    149.             iResult = CreateClient(ConnectionType_Multicast);
    150.             if (iResult == ErrorCode_OK)
    151.                 printf("Client connection type changed to Multicast.\n\n");
    152.             else
    153.                 printf("Error changing client connection type to Multicast.\n\n");
    154.             break;
    155.         case 'u':                            // change to unicast
    156.             iResult = CreateClient(ConnectionType_Unicast);
    157.             if (iResult == ErrorCode_OK)
    158.                 printf("Client connection type changed to Unicast.\n\n");
    159.             else
    160.                 printf("Error changing client connection type to Unicast.\n\n");
    161.             break;
    162.  
    163.  
    164.         default:
    165.             break;
    166.         }
    167.         if (bExit)
    168.             break;
    169.     }
    170.  
    171.     // Done - clean up.
    172.     theClient->Uninitialize();
    173.  
    174.     return ErrorCode_OK;
    175. }
    176. */
    177.  
    178. //NEW INITIALIZATION CODE/////////////////////////////////
    179. int InitializePluginInternal()
    180. {
    181.     printf("InitializePluginInternal.\n");
    182.    
    183.     int iResult;
    184.     int iConnectionType = ConnectionType_Multicast;
    185.     //int iConnectionType = ConnectionType_Unicast;
    186.  
    187.     strcpy(szServerIPAddress, "127.0.0.1");
    188.     strcpy(szMyIPAddress, "127.0.0.1");
    189.  
    190.     // Create NatNet Client
    191.     iResult = CreateClient(iConnectionType);
    192.     if (iResult != ErrorCode_OK)
    193.     {
    194.         printf("Error initializing client.  See log for details.  Exiting");
    195.         return 1;
    196.     }
    197.     else
    198.     {
    199.         printf("Client initialized and ready.\n");
    200.     }
    201.  
    202.     // send/receive test request
    203.     printf("[SampleClient] Sending Test Request\n");
    204.     void* response;
    205.     int nBytes;
    206.     iResult = theClient->SendMessageAndWait("TestRequest", &response, &nBytes);
    207.     if (iResult == ErrorCode_OK)
    208.     {
    209.         printf("[SampleClient] Received: %s", (char*)response);
    210.     }
    211.  
    212.     // Retrieve Data Descriptions from server
    213.     printf("\n\n[SampleClient] Requesting Data Descriptions...");
    214.     sDataDescriptions* pDataDefs = NULL;
    215.     int nBodies = theClient->GetDataDescriptions(&pDataDefs);
    216.     if (!pDataDefs)
    217.     {
    218.         printf("[SampleClient] Unable to retrieve Data Descriptions.");
    219.     }
    220.     else
    221.     {
    222.         printf("[SampleClient] Received %d Data Descriptions:\n", pDataDefs->nDataDescriptions);
    223.         for (int i = 0; i < pDataDefs->nDataDescriptions; i++)
    224.         {
    225.             printf("Data Description # %d (type=%d)\n", i, pDataDefs->arrDataDescriptions[i].type);
    226.             if (pDataDefs->arrDataDescriptions[i].type == Descriptor_MarkerSet)
    227.             {
    228.                 // MarkerSet
    229.                 sMarkerSetDescription* pMS = pDataDefs->arrDataDescriptions[i].Data.MarkerSetDescription;
    230.                 printf("MarkerSet Name : %s\n", pMS->szName);
    231.                 for (int i = 0; i < pMS->nMarkers; i++)
    232.                     printf("%s\n", pMS->szMarkerNames[i]);
    233.             }
    234.             else if (pDataDefs->arrDataDescriptions[i].type == Descriptor_RigidBody)
    235.             {
    236.                 //ORIGINAL CODE START
    237.  
    238.                 // RigidBody
    239.                 sRigidBodyDescription* pRB = pDataDefs->arrDataDescriptions[i].Data.RigidBodyDescription;
    240.                 printf("RigidBody Name : %s\n", pRB->szName);
    241.                 printf("RigidBody ID : %d\n", pRB->ID);
    242.                 printf("RigidBody Parent ID : %d\n", pRB->parentID);
    243.                 printf("Parent Offset : %3.2f,%3.2f,%3.2f\n", pRB->offsetx, pRB->offsety, pRB->offsetz);
    244.                 //ORIGINAL CODE END
    245.             }
    246.             else if (pDataDefs->arrDataDescriptions[i].type == Descriptor_Skeleton)
    247.             {
    248.                 // Skeleton
    249.                 sSkeletonDescription* pSK = pDataDefs->arrDataDescriptions[i].Data.SkeletonDescription;
    250.                 printf("Skeleton Name : %s\n", pSK->szName);
    251.                 printf("Skeleton ID : %d\n", pSK->skeletonID);
    252.                 printf("RigidBody (Bone) Count : %d\n", pSK->nRigidBodies);
    253.                 for (int j = 0; j < pSK->nRigidBodies; j++)
    254.                 {
    255.                     sRigidBodyDescription* pRB = &pSK->RigidBodies[j];
    256.                     printf("  Skeleton RigidBody Name : %s\n", pRB->szName);
    257.                     printf("  Skeleton RigidBody ID : %d\n", pRB->ID);
    258.                     printf("  Skeleton RigidBody Parent ID : %d\n", pRB->parentID);
    259.                     printf("  Parent Offset : %3.2f,%3.2f,%3.2f\n", pRB->offsetx, pRB->offsety, pRB->offsetz);
    260.  
    261.                     // populate bone name dictionary for use in xml ==--
    262.                     gBoneNames[pRB->ID] = pRB->szName;
    263.                 }
    264.             }
    265.             else
    266.             {
    267.                 printf("Unknown data type.");
    268.                 // Unknown
    269.             }
    270.         }
    271.     }
    272.  
    273.     // Ready to receive marker stream!
    274.     printf("\nClient is connected to server and listening for data...\n");
    275.     int c;
    276.     bool bExit = false;
    277.     while (c = _getch())
    278.     {
    279.         switch (c)
    280.         {
    281.         case 'q':
    282.             bExit = true;
    283.             break;
    284.         case 'r':
    285.             resetClient();
    286.             break;
    287.         case 'p':
    288.             sServerDescription ServerDescription;
    289.             memset(&ServerDescription, 0, sizeof(ServerDescription));
    290.             theClient->GetServerDescription(&ServerDescription);
    291.             if (!ServerDescription.HostPresent)
    292.             {
    293.                 printf("Unable to connect to server. Host not present. Exiting.");
    294.                 return 1;
    295.             }
    296.             break;
    297.         case 'f':
    298.         {
    299.             sFrameOfMocapData* pData = theClient->GetLastFrameOfData();
    300.             printf("Most Recent Frame: %d", pData->iFrame);
    301.         }
    302.         break;
    303.         case 'm':                            // change to multicast
    304.             iResult = CreateClient(ConnectionType_Multicast);
    305.             if (iResult == ErrorCode_OK)
    306.                 printf("Client connection type changed to Multicast.\n\n");
    307.             else
    308.                 printf("Error changing client connection type to Multicast.\n\n");
    309.             break;
    310.         case 'u':                            // change to unicast
    311.             iResult = CreateClient(ConnectionType_Unicast);
    312.             if (iResult == ErrorCode_OK)
    313.                 printf("Client connection type changed to Unicast.\n\n");
    314.             else
    315.                 printf("Error changing client connection type to Unicast.\n\n");
    316.             break;
    317.  
    318.  
    319.         default:
    320.             break;
    321.         }
    322.         if (bExit)
    323.             break;
    324.     }
    325.  
    326.     // Done - clean up.
    327.     theClient->Uninitialize();
    328.  
    329.     return ErrorCode_OK;
    330. }
    331.  
    332. //UNITY FUNCTIONS///////////////////////////////
    333. extern "C"
    334. {
    335.     int EXPORT_API InitializePlugin() {
    336.         int iResult;
    337.         iResult = InitializePluginInternal();
    338.         return iResult;
    339.     }
    340.  
    341.     float EXPORT_API GetRigidBodyX(int ID) {
    342.         for (int i = 0; i < rigidBodyArraySize; i++) {
    343.             if (rigidBodyIDs[i] == ID) {
    344.                 return rigidBodyX[i];
    345.             }
    346.             else {
    347.                 return 666.0;
    348.             }
    349.         }
    350.     }
    351.  
    352.     int EXPORT_API GetRigidBodyID(int i) {
    353.         return rigidBodyIDs[i];
    354.     }
    355. }
    356.  
    InitializeMotiveToUnityPlugin.cs
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System;
    4. using System.Runtime.InteropServices;
    5.  
    6. public class InitializeMotiveToUnityPlugin : MonoBehaviour {
    7.  
    8.     [DllImport ("MotiveToUnityPlugin")]
    9.     private static extern int InitializePlugin();
    10.  
    11.     void Awake() {
    12.         Debug.Log("Initializing Plugin...");
    13.         int iResult = InitializePlugin();
    14.         if(iResult == 1) {
    15.             Debug.Log("Error initializing client.");
    16.         }
    17.         if(iResult == 0) {
    18.             Debug.Log("ErrorCode_OK.");
    19.         }
    20.     }
    21. }