C#:调用 C++带有 char** 参数的 DLL

发布于 2024-08-10 23:12:25 字数 596 浏览 3 评论 0原文

我想从我的 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?另外,有什么方法可以不必将我的函数声明为“不安全”?

I would like to call this C++ function from my C# code:

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

To call it in C++, I just define an array of char*:

char* aNames[20];

And allocate each name in a loop:

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

Then call:

GetArrayOfNames(aNames, 20);

In my C# code, I have:

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

Now, how do I do the memory allocation and call GetArrayOfNames? Also, any way of not having to declare my function as "unsafe"?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦幻的味道 2024-08-17 23:12:25

大概:

static extern void GetArrayOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr] StringBuilder[] args, int count);

// Call using
StringBuilder[] arr = new StringBuilder[20];
for (int i = 0; i < arr.Length; i++)
{
    arr[i] = new StringBuilder(50);
}
GetArrayOfNames(arr, arr.Length);

Probably:

static extern void GetArrayOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr] StringBuilder[] args, int count);

// Call using
StringBuilder[] arr = new StringBuilder[20];
for (int i = 0; i < arr.Length; i++)
{
    arr[i] = new StringBuilder(50);
}
GetArrayOfNames(arr, arr.Length);
千鲤 2024-08-17 23:12:25

据我了解 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;
}

As I understand char** is just a reference to string. I created a small test for myself and it worked fine:

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

The implementation of function in C++ is:

TESTCPPLIB_API int fnTestCppLib(char ** str)
{
    *str = "test";
    return 42;
}
浪漫人生路 2024-08-17 23:12:25

这最终工作了:

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

This ended up working:

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

And called/setup like this:

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

int nbOfNames = 2;
GetArrayOfNames(intArr, nbOfNames);

And to put back in a string:

string tmp;
tmp = Marshal.PtrToStringAnsi(intArr[i]);
儭儭莪哋寶赑 2024-08-17 23:12:25

我可以帮你吗?我的 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)));
    }
}

抱歉我的英语。

Can i help you? my sample code in 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);
    };
}

and in C# i call:

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

Sorry for my english.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文