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

本文关键字:dll 结构 C++ | 更新日期: 2023-09-27 18:09:52

我是一名汽车工程师,我的公司决定购买API仅在C++中的硬件(我得到了未经管理的dll和头文件(。问题是,我只使用C#进行了编码,而且我们的大多数应用程序都很容易构建,因为硬件提供商总是在C#(托管dll(中为我们提供API。我现在需要将未经管理的dll中的所有函数转换为C#函数。在我遇到之前一切都很顺利

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;

我不知道如何使用它,因为这个结构是一个函数的参数,例如:

VTC1010_CAN_BUS_API int  CAN_Transmission(can_msg_t *msg);

请帮帮伙计们。不要因为我缺乏知识而开始抨击我。我试着找,但对我来说太难了。

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

假设您不知道如何在.net托管应用程序中使用未经修改的dll,我可以告诉您一些非常基本的事情。方法是使用Visual C++为非托管类创建一个"包装器",然后可以使用此包装器中定义的类来操作未管理的代码。

你可以在这里找到一个好的教程:http://www.codeproject.com/Articles/14180/Using-Unmanaged-C-Libraries-DLLs-in-NET-Applicatio

很抱歉,不要说得更具体,但你需要在创建代码之前开始学习。祝你好运

这里有一个通过p/Invoke Interop Assistant筛选的快速而肮脏的转换。

输入代码:

#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);

输出代码:

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;
    }
}

它是有效的,但当我把一个结构作为自变量时,我感到困惑,这就是为什么我问这个问题