嵌入式mono的c++调用c#示例

      一、支持

      通过mono, c++调用c#的可以传入的参数类型支持类型有:

      1、基本数据类型(bool float double enum...)

      2、引用类型

      3、结构体类型

      4、类对象

      5、数组

      6、指针数组

      7、字符串

      mono环境搭建方法,参考上一篇博客

     二、示例

      下面代码演示,各种类型调用的方法:

       mian.cpp和test_case.h在c++工程中

     TestSharp.cs在c#dll中

     main.cpp


#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/class.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/mono-config.h>
#include "TestCase.h"

MonoDomain* domain;


int main()
{
	// Program.cs所编译dll所在的位置
	const char* managed_binary_path = "G:/Project/Mono/MonoTest/MonoDll/bin/Debug/netcoreapp3.1/MonoDll.dll";

	//获取应用域
	domain = mono_jit_init("Test");

	//加载程序集ManagedLibrary.dll
	MonoAssembly* assembly = mono_domain_assembly_open(domain, managed_binary_path);
	MonoImage* image = mono_assembly_get_image(assembly);

	// =====================================================准备调用
	//获取MonoClass,类似于反射
	MonoClass* main_class = mono_class_from_name(image, "MonoDll", "TestCSharp");

	// 创建类对象
	MonoObject* mono_object = mono_object_new(domain, main_class);

	TestCase1(mono_object);
	TestCase2(mono_object);
	TestCase3(mono_object);
	TestCase4(mono_object, image);
	TestCase5(mono_object, image);
	TestCase6(mono_object);



	//释放应用域
	mono_jit_cleanup(domain);

	return 0;
}

test_case.h

#pragma once
#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/class.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/mono-config.h>
#include <iostream>
#include <vector>


struct struct_test
{
    float f = 3.5;
    double d = 6.555;
    MonoString* s;
};

class class_test
{
    float f = 90.5;
    double d = 110.452;
    MonoString* s;
};

struct struct_test1
{
    float f;
    double d;
};


void TestCase1(MonoObject *mono_object)
{
    MonoDomain *domain = mono_object_get_domain(mono_object);
    MonoClass* mono_class = mono_object_get_class(mono_object);


    //获取要调用的MonoMethodDesc,主要调用过程
    MonoMethodDesc* entry_point_method_desc = mono_method_desc_new(":.ctr()", false);
    MonoMethod* entry_point_method = mono_method_desc_search_in_class(entry_point_method_desc, mono_class);
    mono_method_desc_free(entry_point_method_desc);

    if (entry_point_method != nullptr)
    {
        mono_runtime_invoke(entry_point_method, mono_object, nullptr, nullptr);
    }
}

// 基础参数类型调用
void TestCase2(MonoObject* mono_object)
{
    MonoClass* mono_class = mono_object_get_class(mono_object);
    bool e = false;
    float f = 93.4f;
    double d = 8.3f;
    int i = 6;

    void* p[4];
    p[0] = &e;
    p[1] = &f;
    p[2] = &d;
    p[3] = &i;

    MonoMethod * mono_method = mono_class_get_method_from_name(mono_class, "TestBaseTypeParameter", 4);

    if (mono_method != nullptr)
    {
        mono_runtime_invoke(mono_method, mono_object, p, nullptr);
    }

}

void TestCase3(MonoObject* mono_object)
{
    MonoClass* mono_class = mono_object_get_class(mono_object);

    bool e = false;
    float f = 93.4;
    double d = 8.3f;
    int i = 6;

    void* p[4];
    p[0] = &e;
    p[1] = &f;
    p[2] = &d;
    p[3] = &i;

    MonoMethod* mono_method = mono_class_get_method_from_name(mono_class, "TestBaseTypeRefParameter", 4);

    if (mono_method != nullptr)
    {
        mono_runtime_invoke(mono_method, mono_object, p, nullptr);

        std::cout << e << " " << f << " " << d << " " << i << std::endl;
    }
}

// 数组
void TestCase4(MonoObject* mono_object, MonoImage *image)
{
    MonoClass* mono_class = mono_object_get_class(mono_object);
    MonoDomain* domain = mono_object_get_domain(mono_object);

    //获取MonoClass,类似于反射
    MonoClass* main_class1 = mono_class_from_name(image, "MonoDll", "struct_test1");

    std::vector<struct_test> array_s;
    struct_test s_t;
    array_s.push_back(s_t);
    array_s.push_back(s_t);
    array_s.push_back(s_t);
    array_s.push_back(s_t);

    MonoArray * mono_array = mono_array_new(domain, main_class1, array_s.size());

    for (int i = 0; i < array_s.size(); i++)
    {
        mono_array_set(mono_array, struct_test, i, array_s[i]);
    }


    MonoMethod* mono_method = mono_class_get_method_from_name(mono_class, "TestArrayParameter", 1);

    void* p[1];
    p[0] = mono_array;
    if (mono_method != nullptr)
    {
        mono_runtime_invoke(mono_method, mono_object, p, nullptr);
    }
}

//  对象参数
void TestCase5(MonoObject* mono_object, MonoImage* image)
{
    MonoClass* mono_class = mono_object_get_class(mono_object);
    MonoDomain* domain = mono_object_get_domain(mono_object);

    //获取MonoClass,类似于反射
    MonoClass* main_class1 = mono_class_from_name(image, "MonoDll", "class_test");

    MonoObject* mono_object1 = mono_object_new(domain, main_class1);

    MonoClassField*  mono_class_field = mono_class_get_field_from_name(main_class1, "f");
    float f = 3;
    mono_field_set_value(mono_object1, mono_class_field, &f);

    mono_class_field = mono_class_get_field_from_name(main_class1, "d");
    double d = 6.44;
    mono_field_set_value(mono_object1, mono_class_field, &d);

    MonoMethod* mono_method = mono_class_get_method_from_name(mono_class, "TestClassParameter", 1);

    void* p[1];
    p[0] = mono_object1;
    if (mono_method != nullptr)
    {
        mono_runtime_invoke(mono_method, mono_object, p, nullptr);
    }

}

void TestCase6(MonoObject* mono_object)
{
    MonoClass* mono_class = mono_object_get_class(mono_object);

    struct_test1  e[4];

    void* p[1];
    p[0] = &e;

    MonoMethod* mono_method = mono_class_get_method_from_name(mono_class, "TestPointParameter", 1);

    if (mono_method != nullptr)
    {
        mono_runtime_invoke(mono_method, mono_object, p, nullptr);
    }
}

TestSharp.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace MonoDll
{
    public struct struct_test
    {
        public float f;
        public double d;
        public string s;
    }

    public struct struct_test1
    {
        public float f;
        public double d;
    }

    public class class_test
    {
        public float f;
        public double d;
        public string s;
    }

    public class TestCSharp
    {
        // 构造函数
        public TestCSharp()
        {
            Console.WriteLine("TestCSharp");
        }

        // 基础参数类型调用
        public void TestBaseTypeParameter( bool e,  float f,  double d,  int i)
        {
            Console.WriteLine("TestBaseTypeParameter {0} {1} {2} {3}", e, f, d, i);
        }

        // 基础参数引用调用
        public void TestBaseTypeRefParameter(ref bool e, ref float f, ref double d, ref int i)
        {
            Console.WriteLine("TestBaseTypeRefParameter {0} {1} {2} {3}", e, f, d, i);
        }

        // 数组
        public void TestArrayParameter(struct_test[] ss)
        {
            for (int i = 0; i < ss.Length; i++)
            {
                var s = ss[i];
                Console.WriteLine("ArrayParameter index {0}", i);
                Console.WriteLine("ArrayParameter {0} {1} {2}", s.f, s.d, s.s);
            }
        }

        //  对象参数
        public void TestClassParameter(class_test c)
        {
            Console.WriteLine("TestClassParameter {0} {1} {2}", c.f, c.d, c.s);
        }

        // 传入地址的数组
        unsafe public void TestPointParameter(IntPtr ptr, int count)
        {
           void *p = ptr.ToPointer();

            struct_test1* p1 = (struct_test1*)p;
            for (int i = 0; i < count; i++)
            {
                Console.WriteLine("TestPointParameter {0} {1}", p1[i].d, p1[i].f);
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/q943520218/article/details/108429396