'无法封送'返回值':无效的托管/非托管类型组合。'而使用字符串数组编组委托

时间:2017-10-19 07:41:01

标签: c# c++ c++-cli

我试图将委托封送到函数指针。委托的返回类型是字符串数组,而函数指针的返回类型是char **

以下代码抛出无效的托管/非托管类型组合异常。我该如何解决这个问题?

//  unmanaged code

typedef char** (*MyFuncPtr)(void);

class __declspec(dllexport) MyUnmanagedClass{
private:
    MyFuncPtr mFunPtr
public:

    MyUnmanagedClass(MyFuncPtr funPtr)
    {
        mFunPtr = funPtr;
    }

    char* Func1()
    {
        //  callback
        mFunPtr();

        return "something";
    }
};

//  managed wrapper (CLI)

public delegate cli::array<String^>^ MyDelegate();

public class MyCliClass{
private:
    MyDelegate mDel;
public:

    MyCliClass(MyDelegate del)
    {
        mDel = del;
    }

    String^ Func2()
    {
        MyFuncPtr funPtr = static_cast<MyFuncPtr>(Marshal::GetFunctionPointerForDelegate(mDel).ToPointer());

        MyUnmanagedClass* muc = new MyUnmanagedClass(funPtr);
        char* retValPtr = muc->Func1();

        return context->marshal_as<String^>(retValPtr);
    }   
};

//  managed client (C#)
class Program
{
    static void Main( string[] args )
    {
        MyCliClass mcc = new MyCliClass(Func3);
        mcc.Func2();
    }

    static string[] Func3()
    {
        return new[] { "Some 1", "Some 2" };
    }
}

1 个答案:

答案 0 :(得分:0)

这就是我最终解决它的方法......

//  unmanaged code
class __declspec(dllexport) NativeInterface
{
public:
    vector<string> NativeInterfaceFunc() = 0;
};

class __declspec(dllexport) UnmanagedClass{
private:
    NativeInterface* mNativeInterface
public:

    UnmanagedClass(NativeInterface* nativeInterface)
    {
        mNativeInterface = nativeInterface;
    }

    string UnmanagedClassFunc()
    {
        vector<string> values = mNativeInterface->NativeInterfaceFunc();

        ostringstream oss;

        copy(values.begin(), values.end(), ostream_iterator<string>(oss, ","));

        return oss.str();
    }
};

//  managed wrapper (CLI)
class NativeClass : NativeInterface
{
public:
    NativeInterface(ManagedInterface^ managedInterface)
    {
        mManagedInterface = managedInterface        
    };

    vector<string> NativeInterfaceFunc()
    {
        IEnumerable<String^> managedReturn = mManagedInterface->ManagedInterfaceFunc();

        vector<string> nativeReturn;

        marshal_context^ context = new marshal_context();

        for each(String^ manRet in managedReturn)
        {
            nativeReturn.push_back(context->marshal_as<const char*>(manRet))
        }

        delete context;

        return nativeReturn;
    };
private:
    gcroot<ManagedInterface^> mManagedInterface;
};

public ref class CliClass{
public:

    CliClass(ManagedInterface^ managedInterface)
    {
        mNativeInterface = new NativeClass(managedInterface);

        mUnmanagedClass = new UnmanagedClass(mNativeInterface);
    }

    ~CliClass()
    {
        delete mUnmanagedClass;
        delete mNativeInterface;
    }

    String^ CliFunc()
    {
        string nativeReturn = mUnmanagedClass->UnmanagedClassFunc();

        return gcnew String(nativeReturn.c_str());
    }   
private:
    UnmanagedClass mUnmanagedClass;
    NativeInterface mNativeInterface;
};

//  managed interface (C#)
interface ManagedInterface
{
    IEnumerable<string> ManagedInterfaceFunc();
}

//  managed interface implementation(C#)
public class ManagedClass : ManagedInterface
{
    public IEnumerable<string> ManagedInterfaceFunc()
    {
        return new List<string> { "Some 1", "Some 2" };
    }
}

//  managed client (C#)
class Program
{
    static void Main( string[] args )
    {
        MyCliClass mcc = new MyCliClass(new ManagedClass());

        Console.WriteLine(mcc.CliFunc());

        mcc.Dispose();
    }
}