如何从DLL设置委托/回调(C和C#之间的互操作) [英] How to setup delegate/callback from DLL (interop between C and C#)

查看:389
本文介绍了如何从DLL设置委托/回调(C和C#之间的互操作)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个静态库(* .a为iOS),包含一些函数,我需要分配给一个回调从C#。代码工作正常没有回调,但当我添加委托到结构,它失败,并出现以下错误:

I have a static library (*.a for iOS) that contains some functions that I need to assign to a callback from C#. The code works fine without the callback, but when I add the delegate to the structure, it fails with the following error:

ArgumentException: The specified structure must be blittable or have
layout information. Parameter name: structure at
FMOD_Listener.LoadPlugins () [0x00000] in <filename unknown>:0  at
FMOD_Listener.Initialize () [0x00000] in <filename unknown>:0 
(Filename: currently not available on il2cpp Line: -1)

(C):

extern "C" {
    typedef void (F_CALLBACK *basic_callback)  (int *value1);

    typedef struct telephone
    {
        int area_code;
        int number;
        basic_callback  basic_callbck;
    } TELEPHONE;

    F_DECLSPEC F_DLLEXPORT void F_STDCALL AigooRegisterPhone(TELEPHONE **telephone);

    void F_CALLBACK aigoo_basic_callback(int *value1)
    {
        *value1 = *value1 * 10 ;
    }

    F_DECLSPEC F_DLLEXPORT void F_STDCALL AigooRegisterPhone(TELEPHONE **telephone)
    {
        TELEPHONE* myPhone = new TELEPHONE ();
        myPhone->area_code = 929;
        myPhone->number = 823;
        myPhone->basic_callbck = aigoo_basic_callback;
        *telephone = myPhone;
    }
}

这是管理端C#:

public delegate void basic_callback (ref int value1);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TELEPHONE
{
    public int area_code;
    public int number;
    public basic_callback               basic_callbck;
}

public class FMODPlugInHandler {

    [DllImport ("__Internal")]
    public static extern void AigooRegisterPhone(out IntPtr TelephonePtr);

}

public class FMOD_Listener : MonoBehaviour
{

...

    void LoadPlugins()
    {

        int plugin_result = 0;

        if (Application.platform == RuntimePlatform.IPhonePlayer) {

            IntPtr PhoneIntPtr;
            FMODPlugInHandler.AigooRegisterPhone(out PhoneIntPtr);
            plugin_result = 823823823;
            myLog = "plugin_result = " + plugin_result + " PhoneIntPtr: " + PhoneIntPtr;
            if (PhoneIntPtr != IntPtr.Zero){
                TELEPHONE MyPhone = (TELEPHONE)Marshal.PtrToStructure(PhoneIntPtr, typeof(TELEPHONE));
                plugin_result = 123456;
                myLog = "result = " + plugin_result + " number: " + MyPhone.number ;

                int int_cs = 2;
                plugin_result = MyPhone.basic_callbck(ref int_cs);
                myLog = "result = " + plugin_result + " number: " + MyPhone.number + " int_cs: " + int_cs;
            }
        }        
    }
...
}


推荐答案

这里是基于@Josh Peterson的建议的工作代码。 C代码是一样的。

Here is the working code based on the suggestion from @Josh Peterson. The C code is the same. Only changed the C# side.

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TELEPHONE
{
    public int area_code;
    public int number;
    public **IntPtr** basic_callbck_intptr;
}

...


public class FMOD_Listener : MonoBehaviour
{

...

    void LoadPlugins()
    {

        int plugin_result = 0;

        if (Application.platform == RuntimePlatform.IPhonePlayer) {

            IntPtr PhoneIntPtr;
            FMODPlugInHandler.AigooRegisterPhone(out PhoneIntPtr);
            plugin_result = 823823823;
            myLog = "plugin_result = " + plugin_result + " PhoneIntPtr: " + PhoneIntPtr; 
            if (PhoneIntPtr != IntPtr.Zero){
                TELEPHONE MyPhone = (TELEPHONE)Marshal.PtrToStructure(PhoneIntPtr, typeof(TELEPHONE));
                plugin_result = 123456;
                myLog = "result = " + plugin_result + " number: " + MyPhone.number ; 

                int int_cs = 2; 
                IntPtr basic_callbck_intptr = MyPhone.basic_callbck_intptr;
                basic_callback basic_callbck = Marshal.GetDelegateForFunctionPointer(basic_callbck_intptr, typeof(basic_callback)) as basic_callback;

                basic_callbck(ref int_cs);
                myLog = "result = " + plugin_result + " number: " + MyPhone.number + " int_cs: " + int_cs; 

            }
        }

这篇关于如何从DLL设置委托/回调(C和C#之间的互操作)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆