• Mixing unmanaged C++ and CSharp


    因为新项目将主要用到CSharp,并同时会涉及Mix programming的问题,与Native C++ and C++ CLI (common language infrastructure),今天迅速的google下,做些初步了解先。

    现在的理解:

    1. 这里说的mix programming的意思应该是:让CSharp的module,Native C++ module和C++ CLI的module之间可以互相调用。当然不是把这不同语言的code直接写在一起喽。。

    2. Csharp的module使用Native C++ module的方法已知的有:

      a. 用C++ CLI把native c++ module 包个wrapper module出来,然后,让CSharp的module调用这个wrapper。而且,通过makefile,还可以把这些相关的不同语言写的module打包成一个exe!

      b. 直接用C#的语法 + 使用Native C++导出函数的方式来调用(要在C#代码中调用C++函数,大体的思路是这样的:首先将C++函数写成DLL形式的库,然后在C#中导入DLL中的函数进行调用)。

        1. 大概的样子如下:    

        C++代码:

        1 int StaticElementNumber = 10;

        2  extern "C" AFX_API_EXPORT int GetArrayElementNumber()

        3 {

        4         return StaticElementNumber;

        5 }

        C#代码:
        (导入函数部分,写在调用函数所在类中)

        1 [DllImport("MFCDll.dll")]

        2  public static extern int GetArrayElementNumber();

        3  int ElementNumber = GetArrayElementNumber();

        2. 由于这两种语言中在数据类型上的不同,使得在使用native c++的导出函数时,肯定没法做到fucntion interface一模一样;但是在CLR的帮助下,下面几种类型是可以被有效处理好的:

          a. (C++) extern "C" AFX_API_EXPORT HBITMAP GetABitmap(WCHAR *strFileName) =>      

          (CSharp) public static extern IntPtr GetABitmap([MarshalAs(UnmanagedType.LPWStr)] string strFileName);

          b. (C++) extern "C" AFX_API_EXPORT bool GetArray(int ElementNumber, double *BaseAddress) =>

          (CSharp) public static extern bool GetArray(int ElementNumber, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] double[] BaseAddress);

        3. C# 工程setting中,可以设置是否debug unmanaged code debugging,从而在这种情况下,在运行CSharp module时,直接debug进入C++ module哦!

    3. System.Runtime.InteropServices.Marshal

    4. 转载一篇Q&A (http://bytes.com/topic/c-sharp/answers/715638-mixing-unmanaged-c-c)

     Mixing unmanaged C++ and C#

    Jon Slaughter
    Guest
     
    Posts: n/a
    #1: Sep 29 '07
    How difficult is it for one to integrate unmanaged C++ into C#? I know for
    functions one can use DLLimport but how does one go about doing it for
    classes? Do I have to completely reimplement the classes in managed C++ as a
    wrapper to the unmanaged C++ classes or is there an easier way?

    Essentially what I have done is written a C++ kernel mode driver and I want
    to use it from my C# program. Because it requires some setup outside the
    kernel(because it has to pass buffers back and forth and extract the
    information out of the buffers) I'd rather keep the that specific code
    unmanaged because its probably slightly faster.

    But I don't want to have a huge number of dll imports and write a C# wrapper
    class over each of the imports because it seems a little excessive. (Not
    only does the driver internally use a similar class but I'd essentially be
    implementing the same class 3 times... one in the driver, which is actually
    slightly different but pretty much with same interface, one in unmanaged C++
    to interface with the driver, and some type of managed wrapper.)

    Is there a better way? Can I just mix unmanaged and managed C++ in the same
    project to do all the work and not have to end up with a C# wrapper?
    Basically I think I can get away with just using unsafe code to work with
    the buffers. I'm mainly worried about the performance hit associated with
    doing this. From my initial tests C# is anywhere from 2-5 times slower at
    calling kernel mode drivers than unmanaged C++(not sure if I can get any
    speed up by indirectly referencing unamanged C++ though so I might take that
    hit no matter what if I plan on using C#). Of course I don't want to end up
    with having to change 3 classes every time I make a simple change either.

    Any ideas?

    Thanks,
    Jon


    Most accurate C++ to C# converter. Free demo, support, & updates.

    Willy Denoyette [MVP]
    Guest
     
    Posts: n/a
    #2: Sep 29 '07

    re: Mixing unmanaged C++ and C#


    "Jon Slaughter" <Jon_Slaughter@Hotmail.comwrote in message
    news:A4kLi.55678$YL5.43177@newssvr29.news.prodigy. net...
    Quote:
    How difficult is it for one to integrate unmanaged C++ into C#? I know for
    functions one can use DLLimport but how does one go about doing it for
    classes? Do I have to completely reimplement the classes in managed C++ as
    a wrapper to the unmanaged C++ classes or is there an easier way?
    >
    C++ classes cannot be used directly from C#, only pure C functions can be
    called through the PInvoke layer.
    The only way you can create instances of unmanaged C++ is by wrapping these
    classes by a managed class that delegates the operations on the unmanaged
    class.
    Quote:
    Essentially what I have done is written a C++ kernel mode driver and I
    want to use it from my C# program. Because it requires some setup outside
    the kernel(because it has to pass buffers back and forth and extract the
    information out of the buffers) I'd rather keep the that specific code
    unmanaged because its probably slightly faster.
    >
    Not necessarely, keep in mind that you are adding a layer and as such you
    are extending the path to the final code.
    ..
    Quote:
    But I don't want to have a huge number of dll imports and write a C#
    wrapper class over each of the imports because it seems a little
    excessive. (Not only does the driver internally use a similar class but
    I'd essentially be implementing the same class 3 times... one in the
    driver, which is actually slightly different but pretty much with same
    interface, one in unmanaged C++ to interface with the driver, and some
    type of managed wrapper.)
    >
    Is there a better way? Can I just mix unmanaged and managed C++ in the
    same project to do all the work and not have to end up with a C# wrapper?
    Yep, you can have the wrapper and the native code in one project, even in
    the same assembly. C++/CLI can mix native and managed code in a single DLL.
    Quote:
    Basically I think I can get away with just using unsafe code to work with
    the buffers. I'm mainly worried about the performance hit associated with
    doing this. From my initial tests C# is anywhere from 2-5 times slower at
    calling kernel mode drivers than unmanaged C++(not sure if I can get any
    speed up by indirectly referencing unamanged C++ though so I might take
    that hit no matter what if I plan on using C#). Of course I don't want to
    end up with having to change 3 classes every time I make a simple change
    either.
    >
    2-5 times? How did you compile the CS module, how did you declare the
    PInvoke signature (DllImport), what function are you actually calling, what
    are you measuring and how did you measure this?

    The first time you call into unmanaged from managed you'll incur a serious
    call overhead, this is because the CLR has to synthesize and JIT a
    (marshaling) thunk, but once the thunk is created the overhead is very low,
    all depends on the argument types, the number of arguments and the security
    attribute set on the invoked function.
    For instance, calling a function that takes no or only blittable type
    arguments and which has the SuppressUnmanagedCodeSecurity attribute set [1],
    the overhead is only 4 instructions. This is the minimal overhead taken to
    signal the GC that the thread has transitioned into unmanaged or returned
    from unmanaged.
    Functions that take arrays or structures of blit-able types only, take an
    overhead of ~50 instructions, while functions that take string arguments
    [3], incur the highest overhead 50-xxx instructions depending on the type
    unmanaged char (wide char or MBCS), the reason for this is that the
    marshaler needs to convert the managed String representation into the
    unmanaged char or wchar_t representation.

    [1] 4 instructions overhead
    [DllImport("lib.dll"), SuppressUnmanagedCodeSecurity] extern static int
    F(int i);

    [2] ~50 instructions overhead
    [DllImport("lib.dll"), SuppressUnmanagedCodeSecurity] extern static void
    F(int[] ia);

    [3] ~55instructions overhead
    [DllImport("lib.dll"), SuppressUnmanagedCodeSecurity] extern static int
    FS([MarshalAs(UnmanagedType.LPWStr)] string s);
    extern "C" __declspec(dllexport) int __stdcall FS(wchar_t *s){....}

    a minimum of several hundred instruction depending on the string length.
    [DllImport("lib.dll"), SuppressUnmanagedCodeSecurity] extern static int
    FS(string s);
    extern "C" __declspec(dllexport) int __stdcall FS(char *s){....}

    The managed/unmanaged transition is low when compared to a kernel transition
    (+ 4000 instruction), add to that that you will probably execute several
    thousands instruction in the driver, and it becomes apparent that the
    managed/unmanaged overhead becomes negligible. After all, this is the
    overhead the you'll take when using the IO, Socket etc... classes from
    managed code. Performing disk IO from managed code is not measurable slower
    than from unmanaged code.

    Willy.


    Leon Lambert
    Guest
     
    Posts: n/a
    #3: Oct 1 '07

    re: Mixing unmanaged C++ and C#


    I would write a wrapper assembly in managed C++ using IJW (It Just
    works). Following is a link to a Code Project sample that shows how easy
    it is to mix managed and unmanaged C++ I used it and it works great.
    http://www.codeproject.com/managedcpp/ijw_unmanaged.asp

    Hope it works for you.
    Leon Lambert

    Similar C# / C Sharp bytes

  • 相关阅读:
    打破国外垄断,开发中国人自己的编程语言(2):使用监听器实现计算器
    寒假arcpy arcgis python培训通知
    分户图制作工具
    分户图制作工具
    Python3操作AutoCAD
    arcgis更新注记要素类
    arcgis field for cad
    为什么中小学培训这么火,怎么打击也收效甚微?
    arcgis arcmap使用 Python 加载 CAD 数据
    神仙渡劫
  • 原文地址:https://www.cnblogs.com/taoxu0903/p/1671257.html
Copyright © 2020-2023  润新知