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): //ORIGINAL INITIALIZATION CODE///////////////////////////// int _tmain(int argc, _TCHAR* argv[]) { tmainExcuted = true; int iResult; int iConnectionType = ConnectionType_Multicast; //int iConnectionType = ConnectionType_Unicast; // parse command line args if (argc > 1) { strcpy(szServerIPAddress, argv[1]); // specified on command line printf("Connecting to server at %s...\n", szServerIPAddress); } else { strcpy(szServerIPAddress, ""); // not specified - assume server is local machine printf("Connecting to server at LocalMachine\n"); } if (argc > 2) { strcpy(szMyIPAddress, argv[2]); // specified on command line printf("Connecting from %s...\n", szMyIPAddress); } else { strcpy(szMyIPAddress, ""); // not specified - assume server is local machine printf("Connecting from LocalMachine...\n"); } // Create NatNet Client iResult = CreateClient(iConnectionType); if (iResult != ErrorCode_OK) { printf("Error initializing client. See log for details. Exiting"); return 1; } else { printf("Client initialized and ready.\n"); } // send/receive test request printf("[SampleClient] Sending Test Request\n"); void* response; int nBytes; iResult = theClient->SendMessageAndWait("TestRequest", &response, &nBytes); if (iResult == ErrorCode_OK) { printf("[SampleClient] Received: %s", (char*)response); } // Retrieve Data Descriptions from server printf("\n\n[SampleClient] Requesting Data Descriptions..."); sDataDescriptions* pDataDefs = NULL; int nBodies = theClient->GetDataDescriptions(&pDataDefs); if (!pDataDefs) { printf("[SampleClient] Unable to retrieve Data Descriptions."); } else { printf("[SampleClient] Received %d Data Descriptions:\n", pDataDefs->nDataDescriptions); for (int i = 0; i < pDataDefs->nDataDescriptions; i++) { printf("Data Description # %d (type=%d)\n", i, pDataDefs->arrDataDescriptions[i].type); if (pDataDefs->arrDataDescriptions[i].type == Descriptor_MarkerSet) { // MarkerSet sMarkerSetDescription* pMS = pDataDefs->arrDataDescriptions[i].Data.MarkerSetDescription; printf("MarkerSet Name : %s\n", pMS->szName); for (int i = 0; i < pMS->nMarkers; i++) printf("%s\n", pMS->szMarkerNames[i]); } else if (pDataDefs->arrDataDescriptions[i].type == Descriptor_RigidBody) { //ORIGINAL CODE START // RigidBody sRigidBodyDescription* pRB = pDataDefs->arrDataDescriptions[i].Data.RigidBodyDescription; printf("RigidBody Name : %s\n", pRB->szName); printf("RigidBody ID : %d\n", pRB->ID); printf("RigidBody Parent ID : %d\n", pRB->parentID); printf("Parent Offset : %3.2f,%3.2f,%3.2f\n", pRB->offsetx, pRB->offsety, pRB->offsetz); //ORIGINAL CODE END } else if (pDataDefs->arrDataDescriptions[i].type == Descriptor_Skeleton) { // Skeleton sSkeletonDescription* pSK = pDataDefs->arrDataDescriptions[i].Data.SkeletonDescription; printf("Skeleton Name : %s\n", pSK->szName); printf("Skeleton ID : %d\n", pSK->skeletonID); printf("RigidBody (Bone) Count : %d\n", pSK->nRigidBodies); for (int j = 0; j < pSK->nRigidBodies; j++) { sRigidBodyDescription* pRB = &pSK->RigidBodies[j]; printf(" Skeleton RigidBody Name : %s\n", pRB->szName); printf(" Skeleton RigidBody ID : %d\n", pRB->ID); printf(" Skeleton RigidBody Parent ID : %d\n", pRB->parentID); printf(" Parent Offset : %3.2f,%3.2f,%3.2f\n", pRB->offsetx, pRB->offsety, pRB->offsetz); // populate bone name dictionary for use in xml ==-- gBoneNames[pRB->ID] = pRB->szName; } } else { printf("Unknown data type."); // Unknown } } } // Ready to receive marker stream! printf("\nClient is connected to server and listening for data...\n"); int c; bool bExit = false; while (c = _getch()) { switch (c) { case 'q': bExit = true; break; case 'r': resetClient(); break; case 'p': sServerDescription ServerDescription; memset(&ServerDescription, 0, sizeof(ServerDescription)); theClient->GetServerDescription(&ServerDescription); if (!ServerDescription.HostPresent) { printf("Unable to connect to server. Host not present. Exiting."); return 1; } break; case 'f': { sFrameOfMocapData* pData = theClient->GetLastFrameOfData(); printf("Most Recent Frame: %d", pData->iFrame); } break; case 'm': // change to multicast iResult = CreateClient(ConnectionType_Multicast); if (iResult == ErrorCode_OK) printf("Client connection type changed to Multicast.\n\n"); else printf("Error changing client connection type to Multicast.\n\n"); break; case 'u': // change to unicast iResult = CreateClient(ConnectionType_Unicast); if (iResult == ErrorCode_OK) printf("Client connection type changed to Unicast.\n\n"); else printf("Error changing client connection type to Unicast.\n\n"); break; default: break; } if (bExit) break; } // Done - clean up. theClient->Uninitialize(); return ErrorCode_OK; } */ //NEW INITIALIZATION CODE///////////////////////////////// int InitializePluginInternal() { printf("InitializePluginInternal.\n"); int iResult; int iConnectionType = ConnectionType_Multicast; //int iConnectionType = ConnectionType_Unicast; strcpy(szServerIPAddress, "127.0.0.1"); strcpy(szMyIPAddress, "127.0.0.1"); // Create NatNet Client iResult = CreateClient(iConnectionType); if (iResult != ErrorCode_OK) { printf("Error initializing client. See log for details. Exiting"); return 1; } else { printf("Client initialized and ready.\n"); } // send/receive test request printf("[SampleClient] Sending Test Request\n"); void* response; int nBytes; iResult = theClient->SendMessageAndWait("TestRequest", &response, &nBytes); if (iResult == ErrorCode_OK) { printf("[SampleClient] Received: %s", (char*)response); } // Retrieve Data Descriptions from server printf("\n\n[SampleClient] Requesting Data Descriptions..."); sDataDescriptions* pDataDefs = NULL; int nBodies = theClient->GetDataDescriptions(&pDataDefs); if (!pDataDefs) { printf("[SampleClient] Unable to retrieve Data Descriptions."); } else { printf("[SampleClient] Received %d Data Descriptions:\n", pDataDefs->nDataDescriptions); for (int i = 0; i < pDataDefs->nDataDescriptions; i++) { printf("Data Description # %d (type=%d)\n", i, pDataDefs->arrDataDescriptions[i].type); if (pDataDefs->arrDataDescriptions[i].type == Descriptor_MarkerSet) { // MarkerSet sMarkerSetDescription* pMS = pDataDefs->arrDataDescriptions[i].Data.MarkerSetDescription; printf("MarkerSet Name : %s\n", pMS->szName); for (int i = 0; i < pMS->nMarkers; i++) printf("%s\n", pMS->szMarkerNames[i]); } else if (pDataDefs->arrDataDescriptions[i].type == Descriptor_RigidBody) { //ORIGINAL CODE START // RigidBody sRigidBodyDescription* pRB = pDataDefs->arrDataDescriptions[i].Data.RigidBodyDescription; printf("RigidBody Name : %s\n", pRB->szName); printf("RigidBody ID : %d\n", pRB->ID); printf("RigidBody Parent ID : %d\n", pRB->parentID); printf("Parent Offset : %3.2f,%3.2f,%3.2f\n", pRB->offsetx, pRB->offsety, pRB->offsetz); //ORIGINAL CODE END } else if (pDataDefs->arrDataDescriptions[i].type == Descriptor_Skeleton) { // Skeleton sSkeletonDescription* pSK = pDataDefs->arrDataDescriptions[i].Data.SkeletonDescription; printf("Skeleton Name : %s\n", pSK->szName); printf("Skeleton ID : %d\n", pSK->skeletonID); printf("RigidBody (Bone) Count : %d\n", pSK->nRigidBodies); for (int j = 0; j < pSK->nRigidBodies; j++) { sRigidBodyDescription* pRB = &pSK->RigidBodies[j]; printf(" Skeleton RigidBody Name : %s\n", pRB->szName); printf(" Skeleton RigidBody ID : %d\n", pRB->ID); printf(" Skeleton RigidBody Parent ID : %d\n", pRB->parentID); printf(" Parent Offset : %3.2f,%3.2f,%3.2f\n", pRB->offsetx, pRB->offsety, pRB->offsetz); // populate bone name dictionary for use in xml ==-- gBoneNames[pRB->ID] = pRB->szName; } } else { printf("Unknown data type."); // Unknown } } } // Ready to receive marker stream! printf("\nClient is connected to server and listening for data...\n"); int c; bool bExit = false; while (c = _getch()) { switch (c) { case 'q': bExit = true; break; case 'r': resetClient(); break; case 'p': sServerDescription ServerDescription; memset(&ServerDescription, 0, sizeof(ServerDescription)); theClient->GetServerDescription(&ServerDescription); if (!ServerDescription.HostPresent) { printf("Unable to connect to server. Host not present. Exiting."); return 1; } break; case 'f': { sFrameOfMocapData* pData = theClient->GetLastFrameOfData(); printf("Most Recent Frame: %d", pData->iFrame); } break; case 'm': // change to multicast iResult = CreateClient(ConnectionType_Multicast); if (iResult == ErrorCode_OK) printf("Client connection type changed to Multicast.\n\n"); else printf("Error changing client connection type to Multicast.\n\n"); break; case 'u': // change to unicast iResult = CreateClient(ConnectionType_Unicast); if (iResult == ErrorCode_OK) printf("Client connection type changed to Unicast.\n\n"); else printf("Error changing client connection type to Unicast.\n\n"); break; default: break; } if (bExit) break; } // Done - clean up. theClient->Uninitialize(); return ErrorCode_OK; } //UNITY FUNCTIONS/////////////////////////////// extern "C" { int EXPORT_API InitializePlugin() { int iResult; iResult = InitializePluginInternal(); return iResult; } float EXPORT_API GetRigidBodyX(int ID) { for (int i = 0; i < rigidBodyArraySize; i++) { if (rigidBodyIDs[i] == ID) { return rigidBodyX[i]; } else { return 666.0; } } } int EXPORT_API GetRigidBodyID(int i) { return rigidBodyIDs[i]; } } InitializeMotiveToUnityPlugin.cs Code (CSharp): using UnityEngine; using System.Collections; using System; using System.Runtime.InteropServices; public class InitializeMotiveToUnityPlugin : MonoBehaviour { [DllImport ("MotiveToUnityPlugin")] private static extern int InitializePlugin(); void Awake() { Debug.Log("Initializing Plugin..."); int iResult = InitializePlugin(); if(iResult == 1) { Debug.Log("Error initializing client."); } if(iResult == 0) { Debug.Log("ErrorCode_OK."); } } }