【问题标题】:C#: calling C++ DLL with char** argumentC#:使用 char** 参数调用 C++ DLL
【发布时间】:2009-11-10 23:07:06
【问题描述】:

我想从我的 C# 代码中调用这个 C++ 函数:

void GetArrayOfNames(char** names, int nbOfNames);

要在 C++ 中调用它,我只需定义一个 char* 数组:

char* aNames[20];

并在循环中分配每个名称:

for(int i-0; i<20; i++)
{
    aNames[i] = new char[50];
}

然后调用:

GetArrayOfNames(aNames, 20);

在我的 C# 代码中,我有:

[DllImport("MyDLL.dll")]
unsafe static extern void GetArrayOfNames(char** ppNames, int nbOfNames);

现在,我该如何分配内存并调用 GetArrayOfNames?另外,有什么方法不必将我的函数声明为“不安全”?

【问题讨论】:

    标签: c# marshalling


    【解决方案1】:

    大概:

    static extern void GetArrayOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr] StringBuilder[] args, int count); // 调用使用 StringBuilder[] arr = new StringBuilder[20]; for (int i = 0; i

    【讨论】:

      【解决方案2】:

      据我了解,char** 只是对字符串的引用。我为自己创建了一个小测试,效果很好:

      class Program
      {
          [DllImport("TestCppLib.dll", CharSet = CharSet.Ansi, EntryPoint = "?fnTestCppLib@@YAHPAPAD@Z", CallingConvention=CallingConvention.Cdecl)]
          extern static int fnTestCppLib(ref string s);
          static void Main(string[] args)
          {
              var s = "some";
              var t = fnTestCppLib(ref s);
              Debug.Assert(s == "test");
          }
      }
      

      函数在C++中的实现是:

      TESTCPPLIB_API int fnTestCppLib(char ** str)
      {
          *str = "test";
          return 42;
      }
      

      【讨论】:

        【解决方案3】:

        这最终奏效了:

        static extern int GetArrayOfNames(IntPtr[] astr, int iLength);

        并像这样调用/设置:

        IntPtr[] intArr = new IntPtr[200];
        for (int i = 0; i < intArr.Length; i++)
         {
          intArr[i] = Marshal.AllocHGlobal(256);
        }
        
        int nbOfNames = 2;
        GetArrayOfNames(intArr, nbOfNames);
        

        然后放回字符串中:

        string tmp;
        tmp = Marshal.PtrToStringAnsi(intArr[i]);
        

        【讨论】:

          【解决方案4】:

          我能帮你吗?我的 C++ 示例代码:

          //CamMethods.cpp:
          #include <iostream>
          using namespace std;
          #include "CamPS.h"
          
          namespace Export {
              char * CameraPS::CamStart(char *s){
                  return "teste";
              };
          }
          
          //CamPs.h
          namespace Export{
              class CameraPS
              {
              public:
                  _declspec(dllexport) char * _stdcall CamStart(char *s);
              };
          }
          

          在 C# 中我调用:

          using UnityEngine;
          using System;
          using System.Collections;
          using System.Runtime.InteropServices;
          
          public class DllTeste : MonoBehaviour
          {
              public int x;
              [DllImport ("PS_Cam.dll", EntryPoint="CamStart", CallingConvention = CallingConvention.StdCall)]
              private static extern IntPtr CamStart (int s);//i can put <string> in same place of <int>
          
          
              void Start ()
              {
          
              }
          
              void Update ()
              {
          //      IntPtr a =  CamStart(x);
          //      string b = Marshal.PtrToStringAnsi(a);  
          //      Debug.Log(b);
                  Debug.Log(Marshal.PtrToStringAnsi(CamStart(x)));
              }
          }
          

          对不起我的英语。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-11-16
            • 2012-10-30
            • 1970-01-01
            • 2013-07-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多