将 char 数组值从 C++ 传递到 C# 应用程序

Posted

技术标签:

【中文标题】将 char 数组值从 C++ 传递到 C# 应用程序【英文标题】:Pass char array value from C++ to C# app 【发布时间】:2017-09-21 12:48:37 【问题描述】:

我有一个巨大的 C++ 结构,其中包含大量 C++ 验证代码,我想将其导入 C# 项目。我能够转移除 CHAR* 和 CHAR[] 之外的所有值。

使用 CHAR*,我的字符串充满了中国字符但是,如果我去内存中查找,我的字符串在那里,我可以看到“这是一个测试 #1”。

使用 CHAR[x],我只能看到第一个字符,在内存中也是如此。

在下面的测试中,我可以提取整数: value1 = data.Value1; 并且值 1 是 123,但是 CHAR。

问题:我想念什么,为什么我无法使用 char 数组获取值。 谢谢

C++ DLL

//This is the main DLL file.
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

extern "C"

  public struct Data
  
    int Value1;
    char* pValue2;
    char Value3[1024];
  ;

  typedef int( *FN_CCP_INVOKE_NEW_BOARD_OPTIMIZER) (struct Data* data);

  FN_CCP_INVOKE_NEW_BOARD_OPTIMIZER _pInvokeCallback;

  int __declspec(dllexport)  DLLTestCPlusPlus_Initialize()
  
    return 0;
  

  int __declspec(dllexport) DLLTestCPlusPlus_RegisterDllInvokeProcessCallback(void* fnInvokeCaller)
  
    _pInvokeCallback = (FN_CCP_INVOKE_NEW_BOARD_OPTIMIZER)fnInvokeCaller;

    struct Data data;

    // INT
    data.Value1 = 123;

    // CHAR*
    data.pValue2 = new char[1024];
    sprintf(data.pValue2, "This is a test #1");

    // CHAR [1024]
    sprintf(data.Value3, "This is a test #2");

    if (_pInvokeCallback)
    
      _pInvokeCallback(&data);
    

    return 0;
  

这是导入 DLL 的 C# 程序。

using System;
using System.Runtime.InteropServices;

  public unsafe struct Data
  
    public int Value1;
    public char* pValue2;
    public fixed char Value3[1024];
  

  public static class Interop
  
    public delegate Int32 Callback([MarshalAs(UnmanagedType.Struct)] Data data);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool SetDllDirectory(string lpPathName);


    [DllImport("C:\\DATA\\CODE\\ApplicationTestCSharp\\x64\\Debug\\DLLTestCPlusPlus.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern Int32 DLLTestCPlusPlus_Initialize();

    [DllImport("C:\\DATA\\CODE\\ApplicationTestCSharp\\x64\\Debug\\DLLTestCPlusPlus.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern Int32 DLLTestCPlusPlus_RegisterDllInvokeProcessCallback([MarshalAs(UnmanagedType.FunctionPtr)] Callback handler);
  

  public class MyTest
  
    private Interop.Callback _callback = null;

    public MyTest()
    
      int returnCode = 0;

      returnCode = Interop.DLLTestCPlusPlus_Initialize();

      _callback = new Interop.Callback(CallbackHandler);

      returnCode = Interop.DLLTestCPlusPlus_RegisterDllInvokeProcessCallback(_callback);
    

    private Int32 CallbackHandler(Data data)
    
      int value1 = 0;
      string value2 = "";
      string value3 = "";

      unsafe
      
        // INT
        value1 = data.Value1;

        // CHAR* - MUST BE "This is a test #1"
        value2 = new string(data.pValue2);

        // CHAR [1024] - "This is a test #2"
        value3 = new string(data.Value3);
      

      return 1;
    
  

  class Program
  
    static void Main(string[] args)
    
      MyTest myTest = new MyTest();

    
  

【问题讨论】:

Hanzi 建议您将 ASCII 文本传递给期望 UTF-16 的内容。 P/Invoke 让您指定它是什么类型的文本。 在 C# 方面,在您的不安全结构中,使用 byte 而不是 char 并使用 Encoding.Default.GetString 转换为文本。 【参考方案1】:

好的,我找到了,我在结构声明中进行了更改

   /*
      public char* pValue2;
      public fixed char Value3[1024];
      */
      [MarshalAs(UnmanagedType.LPStr)] public String pValue2;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] public String pValue3;

然后像这样提取数据!

  // CHAR* - "This is a test #1";
  // value2 = new string(data.pValue2);
     value2 = data.pValue2

  // CHAR [1024] - "This is a test #2"
  //value3 = new string(data.Value3);
    value3 = data.pValue3;

【讨论】:

以上是关于将 char 数组值从 C++ 传递到 C# 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

将 C# char 数组传递给 C++ 与字节数组不同

将 c++ dll 的 char 指针数组传递给 c# 字符串

将字符串值从 C# 返回到 c++

如何将结构中的char *从c#传递到c++

如何将带有 unsigned char* 的结构从 C# 传递到 C++?

通过互操作将字符串数组从 C# 传递到 C++