C# p/invoke: marshaling class between C# and C++ class

Jin Tu

Blog: http://www.inblogs.net/havdone

1.0 Abstraction

This article provides basic information to realize how pass c# function pointer and class object to a c++ function as parameters.

2.0 Mechanism

The c++ function parameters could be an object pointer or a function pointer. Passing c# class object or a function as parameter to c++ function actually is passing a C# reference or a function pointer. To realize this mechanism properly, first should make sense of the basic knowledge in its scope.

3.0 Basic knowledge

3.1 C# pointer (*)

The c# unsafe code can use pointer directive (*). However, c# pointer has many constraints. As stated in MSDN, “C# pointer types do not inherit from object and no conversions exist between pointer types and object. Also, boxing and unboxing do not support pointers. However, you can convert between different pointer types and between pointer types and integral types.”

“Any of the following types may be a pointer type:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.
  • Any enum type.
  • Any pointer type.
  • Any user-defined struct type that contains fields of unmanaged types only.”

That means c# cannot make conversion from class object reference to pointer type (*). Using “&” operator on a reference, will cause a compiling error “Cannot take the address of, get the size of, or declare a pointer to a managed type”.

3.2 Reference parameters in C#

While reference object, such as a class object, is pass to function as a parameter, actually the address of object is passed, as reference is a pointer type.

3.3 Class data type in memory

[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]

    class Class1

    {

        public int i;

        private int _i;

        public System.Collections.ArrayList arr = new System.Collections.ArrayList();

        public void test()

        {

            Console.WriteLine("hello world!");

        }

 

        public Class1()

        {

            _i = 400;

           

        }    

 

    };

 

The above graph shows how a Class1 object is allocated memory.

3.4 Delegate in C#

The delegate keyword is used to declare a reference type that can be used to encapsulate a named or an anonymous method.”(MSDN)

4.0 Marshaling Example

This example passes class object that mentioned in chapter 3.3, to a c++ dll. C++ code use a class type object to accept the fields values of c# object and use a function pointer parameter to accept c# object function.

 

/

 //C# Code

 ///

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.InteropServices;

 

namespace interoperation

{

    class Program

    {

 

        //

        //P/Invoke a c++ function declare

        ///

        //if do not explcit point out entrypoint

        //the c# function name must be the same with c++ code

        [System.Runtime.InteropServices.DllImport("..//..//..//debug//sort.dll")]

        public static extern void func(Class1 arrays, Program.delgFunc func);

 

        //

        //C# function pointer declare

        ///

        public delegate void delgFunc();

 

        static void Main(string[] args)

        {        

            Class1 obj = new Class1();

            Program.delgFunc delg = obj.test;

 

            //pass a class reference and a function pointer to c++ function

            func(obj, delg);  

           

        }

    };

 

    [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]

    class Class1

    {

        public void test()

        {

            Console.WriteLine("c# function is called");

            Console.WriteLine("_i="+this._i.ToString());

        }

        public System.Collections.ArrayList arr = new System.Collections.ArrayList();

        private int _i;

        public int i;       

 

        public Class1()

        {

            _i = 400;

            i = 333;

        }

     

 

    };

}

 

 

/

 //C++ Code

 ///

// Sort.cpp : Defines the exported functions for the DLL application.

//

 

#include "stdafx.h"

#include <iostream>

using namespace std;

 

 

 

extern "C"

{

     //

     //To accept C# class object,

     //remember c++ fileds are allocated memory sequentially

     ///

     class Class1

     {

     public :

         void * unknow;//accept arr of c# object

         int _i;//accept _i of c# object

         int i;   //accept i of c# object

    

     };

 

      __declspec(dllexport) void func(Class1* class1,void (*   test)())

     {

         cout<<"(C# object is passed !) The value of  private field '_i': "<<class1->_i<<"/n";

         cout<<"(C# object is passed !) The value of  public field 'i': "<<class1->i<<"/n";

         test();

     }

}

The output like this:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值