简体   繁体   English

将C ++结构移植到C#中(从非托管dll)

[英]Porting C++ Structure into C# (from an Unmanaged dll)

I am a Automotive Engineer and my company decided to buy a hardware for which the API was only in C++ ( I got unmanged dll and header files). 我是一名汽车工程师,我的公司决定购买一种仅使用C ++的API的硬件(我得到了未处理的dll和头文件)。 The issue is that I have only coded in C# and most of our applications are very easy to build as the hardware provider always gives us the API in C# (managed dll). 问题是我只用C#编码,并且我们的大多数应用程序都非常易于构建,因为硬件提供程序始终以C#(托管dll)的形式提供API。 I now need to convert all the functions in the unmanged dll to C# functions. 现在,我需要将未管理的dll中的所有函数转换为C#函数。 It was going smooth till I came across 一直很顺利,直到我遇到

typedef struct can_msg
{
    unsigned short ide;                         // Standard/extended msg
    unsigned int id;                            // 11 or 29 bit msg id
    unsigned short dlc;                         // Size of data
    unsigned char data[CAN_MSG_DATA_LEN];       // Message pay load
    unsigned short rtr;                         // RTR message
} can_msg_t;

I have no idea how to use it as this structure is an argument for a function for example: 我不知道如何使用它,因为这种结构是函数的一个参数,例如:

VTC1010_CAN_BUS_API int  CAN_Transmission(can_msg_t *msg);

Please help guys. 请帮助大家。 Do't start bashing me for my lack of knowledge. 不要因为我缺乏知识而羞辱我。 I tried to find but its all too hard for me. 我试图找到,但这对我来说太难了。

Assuming that you don't have knowledge about how to use unamaged dlls in .net managed applications I can tell you some very basic things. 假设您不了解如何在.net托管应用程序中使用未损坏的dll,我可以告诉您一些非常基本的知识。 The way to go is to create a "wrapper" for the unmanaged classes using Visual C++, then you can use the classes defined in this wrapper to operate with your unamanaged code. 可行的方法是使用Visual C ++为非托管类创建“包装器”,然后可以使用此包装器中定义的类对非托管代码进行操作。

You can find a good tutorial here: http://www.codeproject.com/Articles/14180/Using-Unmanaged-C-Libraries-DLLs-in-NET-Applicatio 您可以在这里找到一个很好的教程: http : //www.codeproject.com/Articles/14180/Using-Unmanaged-C-Libraries-DLLs-in-NET-Applicatio

Sorry for don't be more specific, but you need to start to study before create the code. 抱歉,请不要更具体,但是在创建代码之前,您需要开始学习。 Good luck! 祝好运!

Here is a quick and dirty conversion through the P/Invoke Interop Assistant sieve. 这是通过P / Invoke Interop Assistant筛子进行的快速而肮脏的转换。

Input code: 输入代码:

#define CAN_MSG_DATA_LEN 100 // adjust correct value here

typedef struct can_msg
{
    unsigned short ide;                         // Standard/extended msg
    unsigned int id;                            // 11 or 29 bit msg id
    unsigned short dlc;                         // Size of data
    unsigned char data[CAN_MSG_DATA_LEN];       // Message pay load
    unsigned short rtr;                         // RTR message
} can_msg_t;

int  CAN_Transmission(can_msg_t *msg);

Output code: 输出代码:

public partial class NativeConstants {

    /// CAN_MSG_DATA_LEN -> 100
    public const int CAN_MSG_DATA_LEN = 100;
}

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi)]
public struct can_msg {

    /// unsigned short
    public ushort ide;

    /// unsigned int
    public uint id;

    /// unsigned short
    public ushort dlc;

    /// unsigned char[100]
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=100)]
    public string data;

    /// unsigned short
    public ushort rtr;
}

public partial class NativeMethods {

    /// Return Type: int
    ///msg: can_msg_t*
    [System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="CAN_Transmission")]
public static extern  int CAN_Transmission(ref can_msg msg) ;

}
static class NativeMethods
{  


    // To  load dll
    [DllImport("kernel32.dll")]
    public static extern IntPtr LoadLibrary(string dllToLoad);
    // To get the Address of the Function
    [DllImport("kernel32.dll")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    // Freeing up the Library for other usage. 
    [DllImport("kernel32.dll")]
    public static extern bool FreeLibrary(IntPtr hModule);
}
class manageCAN
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    // Declaration of function to get
    private delegate int CAN_Initial(int baudRate);
    private delegate int Library_Release();

    // Getting the String for .dll Address
    static readonly string dllfile = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\VTC1010_CAN_Bus.dll";

    public int IntialiseCAN (int baudrate)
    {
        // Loading dll using Native Methods
        IntPtr pDll = NativeMethods.LoadLibrary(dllfile);
        if (pDll== IntPtr.Zero)
        {
            MessageBox.Show("Loading Failed");
        }   
        // Getting the Adress method
        IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "CAN_Initial");
        CAN_Initial initialiseCAN = (CAN_Initial)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(CAN_Initial));
        int result = initialiseCAN(baudrate);
        bool iresult = NativeMethods.FreeLibrary(pDll);
        return result;
    }
}

It works but I got confused when I got a structure as an argument, that's why I asked this question 它有效,但是当我有一个结构作为参数时,我感到困惑,这就是为什么我问这个问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM