C# 访问本机 C++ DLL

Posted

技术标签:

【中文标题】C# 访问本机 C++ DLL【英文标题】:C# Access To Native C++ DLL 【发布时间】:2019-08-12 01:47:46 【问题描述】:

我正在尝试创建一个访问本机 C++ DLL 的程序。下面是示例代码。

C++ 代码

GetRmaPin (const char *rma_password, const char *serial, unsigned char *rma_pin);

C#代码

class Program

    static void Main ( string [ ] args )
    
        string[] password =  "74f3d3a287cee548c1842c07090d6a274dd0ddbd04bfd1e4694861a369bc7304" ;
        string[] serial =  "184393900006" ;
        //StringBuilder rma_pin = new StringBuilder(2048);
        byte[] rma_pin = new byte[2048];

        int rc = GetRmaPin(password, serial, ref rma_pin);
        Console.WriteLine ( "Result: " + rc.ToString ( ) );
        Console.WriteLine ( "Payload: " + rma_pin.ToString ( ) );
        Console.Read ( );
    

    [DllImport ( "Security.dll" , EntryPoint = "GetRmaPin" , CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetRmaPin (
        [In][MarshalAs ( UnmanagedType.LPArray , ArraySubType = UnmanagedType.LPStr )] string [ ] password ,
        [In][MarshalAs ( UnmanagedType.LPArray , ArraySubType = UnmanagedType.LPStr )] string [ ] serial ,
        ref byte[] rmap_in );

错误信息: 托管调试助手“FatalExecutionEngineError” Message=Managed Debugging Assistant 'FatalExecutionEngineError' : '运行时遇到致命错误。错误地址位于线程 0x97a4 上的 0x732dc93d。错误代码为 0xc0000005。此错误可能是 CLR 中的错​​误或用户代码的不安全或不可验证部分中的错误。此错误的常见来源包括 COM-interop 或 PInvoke 的用户封送错误,这可能会损坏堆栈。'

【问题讨论】:

这是一个设计得很糟糕的函数。很难在 C++ 程序中正确调用,当你必须调用它时,它永远不会变得更好。如果供应商为您提供了调用它的示例 C++ 代码,那么您应该展示它。最有可能的是第三个参数必须是纯字节[],没有引用。您传递的数组必须足够大,以便本机代码不会破坏 GC 堆。志存高远。 @HansPassant 感谢您的回复。我删除了“ref”并为数组分配了 2048 个字节。但是,我需要从第三个参数中获取值,这就是我将“ref”放在那里的原因。删除“ref”可以消除运行时错误,但是如何从这个“unsigned char *”中获取值。不幸的是,这个 API 没有示例代码 :-( 【参考方案1】:

经过一些实验,我找到了一种从第三个参数中获取值的方法。这是更新的代码。感谢@HansPassant 提供删除“参考”的提示。希望这对将来的某人有所帮助。

class Program

    static void Main ( string [ ] args )
    
        string[] password =  "74f3d3a287cee548c1842c07090d6a274dd0ddbd04bfd1e4694861a369bc7304" ;
        string[] serial =  "184393900006" ;
        byte[] rma_pin = new byte[32];

        int rc = GetRmaPin(password, serial, rma_pin);

        Console.WriteLine ( "Result: " + rc.ToString ( ) );
        Console.WriteLine ( "Payload: " + BitConverter.ToString ( rma_pin ).Replace ( "-" , "" ) );
        Console.Read ( );
    

    [DllImport ( "SecurityProduction.dll" , EntryPoint = "GetRmaPin" , CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetRmaPin (
        [In][MarshalAs ( UnmanagedType.LPArray , ArraySubType = UnmanagedType.LPStr )] string [ ] password ,
        [In][MarshalAs ( UnmanagedType.LPArray , ArraySubType = UnmanagedType.LPStr )] string [ ] serial ,
        byte[] rmap_in );

【讨论】:

以上是关于C# 访问本机 C++ DLL的主要内容,如果未能解决你的问题,请参考以下文章

如何将 C# 客户端 RPC 写入远程本机 C++ 服务器?

运行使用 /clr 构建的 DLL 的本机 C++ 应用程序时访问冲突

从c#访问c++ dll库[重复]

使用 C# 访问非托管 C++ DLL 时出现 AccessViolationException

在 C# 中从 C++ DLL 访问指针参数值

从 C# 程序访问 C++ DLL 中的多个函数