3

私は C# とマーシャリングの初心者です。C# で C func を使用する必要がありますが、C func からの戻り値が正しくありません (または、正しい答えに変換する方法がわかりません)。

C ソース:

#include "main.h"

char *Ololo(char *arg, int &n3)
{
    char *szRet;
    szRet=(char*)malloc(strlen(arg)+1);
    strcpy(szRet,arg);
    n3 = strlen(szRet);
    return szRet;
}

C ヘッダー:

extern "C" __declspec(dllexport) char *Ololo(char *arg, int &n3);

C# ソース:

class Program
{
    [DllImport(@"F:\Projects\service\dll\testDLL2.DLL", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
    public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3);

    static void Main(string[] args)
    {
        string n1 = "ololo";
        char[] chars = new char[n1.Length];
        chars = n1.ToCharArray();
        Int32 n3 = 0;
        IntPtr result;
        result = Ololo(chars, ref n3);
        string n4 = Marshal.PtrToStringUni(result,n3);
        Console.WriteLine(n4);
    }
}

「o???」のようなものが返ってきました。

下手な英語でごめんなさい

----------------------解決済み-----------------------

class Program
    {
        [DllImport(@"F:\Projects\service\dll\testDLL2.DLL", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
        public static extern IntPtr Ololo([MarshalAs(UnmanagedType.LPStr)]string arg, ref Int32 n3);

        static void Main(string[] args)
        {
            string n1 = "ololo";
            Int32 n3 = 0;
            int n2 = n1.Length;
            IntPtr result;
            result = Ololo(n1, ref n3);
            string n4 = Marshal.PtrToStringAnsi(result, n3);
            Console.WriteLine(n4);
        }
    }

それはうまくいきます。n3 では 5 を、n4 では ololo! 迅速な回答ありがとうございます。

4

2 に答える 2

3

public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3);

IntPtr基本的に文字列へのポインタではなく文字列を返したいので、は間違った戻りタイプです。Cでは、を使用して文字列へのポインタを使用できます。.NETchar*での同等の機能は、次を使用することです[MarshalAs(UnmanagedType.LPStr)]stringchar* これにより、をstring正しくマーシャリングする必要があります。

IntPtr実際の文字列を取得するためのポインタ型は役に立ちません。

StringBuilderまた、ではなく、マーシャル関数を使用する必要があるようですchar[]。そうすれば、少なくともC関数に正しい文字列を取得する必要があります。

于 2012-09-10T11:52:17.123 に答える
-1

charマーシャラーは、funsiesの配列をNULLで終了しません。あなたがそれを言ったのでそれはそれをします-あなたがそれを言ったならchar.NETのaはUTF-16であり、これは16ビット幅であるため幸運です。2番目のバイトは'o'UTF-16であるためゼロになり、strlenは1になります。 nullで終了するC文字列としての文字列は、あなたが理解しているように見えるよりも少し高いです。それで、マーシャラーにすべての仕事をさせてください-それはすでにこの仕事をする方法を知っています。

public static extern [MarshalAs(UnmanagedType.LPStr)]string Ololo(
    [MarshalAs(UnmanagedType.LPStr)]string arg,
    ref int n3
);
static void Main(string[] args)
{
    string n1 = "ololo";
    Int32 n3 = 0;
    string n4 = Ololo(chars, ref n3);
    Console.WriteLine(n4);
}
于 2012-09-10T12:03:05.473 に答える