Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

How to implement callback functions from C++ DLL

Discussion in 'Scripting' started by TomTom268, Dec 16, 2019.

  1. TomTom268

    TomTom268

    Joined:
    Jul 31, 2018
    Posts:
    4
    Hi,
    I created a DLL from a C++ project and wanted to use its functions in Unity, but I still have difficulties with callbacks. I keep on getting the error EntryPointNotFoundException: WacomMTRegisterAttachCallback.
    Here the C++ file:
    Code (CSharp):
    1. extern "C" {
    2. #include <stdlib.h>
    3.  
    4. typedef enum _WacomMTError
    5. {
    6.     WMTErrorSuccess                = 0,
    7.     WMTErrorDriverNotFound        = 1,
    8.     WMTErrorBadVersion            = 2,
    9.     WMTErrorAPIOutdated            = 3,
    10.     WMTErrorInvalidParam            = 4,
    11.     WMTErrorQuit                    = 5,
    12.     WMTErrorBufferTooSmall        = 6
    13. } WacomMTError;
    14.  
    15. typedef void (__stdcall * WMT_ATTACH_CALLBACK)(WacomMTCapability deviceInfo, void *userData);
    16.  
    17. __declspec(dllexport) WacomMTError __stdcall WacomMTInitialize(int libraryAPIVersion);
    18.  
    19. __declspec(dllexport) WacomMTError __stdcall WacomMTRegisterAttachCallback(WMT_ATTACH_CALLBACK attachCallback, void *userData);
    20.  
    21. }
    22.  
    The C# file in Unity:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.Runtime.InteropServices;
    4. using System;
    5. using UnityEngine;
    6.  
    7.  
    8. enum WacomMTError
    9. {
    10.     WMTErrorSuccess = 0,
    11.     WMTErrorDriverNotFound = 1,
    12.     WMTErrorBadVersion = 2,
    13.     WMTErrorAPIOutdated = 3,
    14.     WMTErrorInvalidParam = 4,
    15.     WMTErrorQuit = 5,
    16.     WMTErrorBufferTooSmall = 6
    17. }
    18.  
    19.  
    20. public class PluginTest : MonoBehaviour {
    21.  
    22.     [DllImport("WacomFeel")]
    23.     private static extern WacomMTError WacomMTInitialize(int libraryAPIVersion);
    24.  
    25.     private delegate void AttachCallbackDel(WacomMTCapability deviceInfo, IntPtr userData);
    26.     [DllImport("WacomFeel")]
    27.     private static extern WacomMTError WacomMTRegisterAttachCallback(AttachCallbackDel attachCallback, IntPtr userData);
    28.  
    29.     private AttachCallbackDel attachCallbackDel;
    30.  
    31.     private static void AttachCallback(WacomMTCapability deviceInfo, IntPtr userData)
    32.     {
    33.         //do something
    34.     }
    35.  
    36.     void Start () {
    37.         WacomMTError test = WacomMTInitialize(4);
    38.         Debug.Log(test); //returns success
    39.  
    40.         attachCallbackDel = new AttachCallbackDel(AttachCallback);
    41.  
    42.         test = WacomMTRegisterAttachCallback(attachCallbackDel, IntPtr.Zero);
    43.         Debug.Log(test); //no return due to error
    44.     }
    45.  
    46. }
    The function WacomMTInitialize works fine, but calling WacomMTRegisterAttachCallback brings an error. Any suggestions?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    My understanding is you cannot call back like that. You have to use the UnitySendMessage() method on the native side, and Unity will get the call to your C# function, but on the next frame.

    See here:

    https://docs.unity3d.com/Manual/PluginsForIOS.html

    This is specifically the iOS plugins page, but I believe it applies to ALL native-C# interop under Unity.

    Quote:

    Calling C# back from native code

    Unity iOS supports limited native-to-managed callback functionality via UnitySendMessage:

    UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");
    This function has three parameters: the name of the target GameObject
    , the script method to call on that object and the message string to pass to the called method.

    Known limitations:

    Only script methods that correspond to the following signature can be called from native code: function MethodName(message:string)
    Calls to UnitySendMessage are asynchronous and have a delay of one frame.
     
  3. TomTom268

    TomTom268

    Joined:
    Jul 31, 2018
    Posts:
    4