Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DLL中CARR*的结构值从C++到C节(编组/ pJoCKE) 我现在有一个DLL,它有一个结构,我声明它将被C和C++应用程序用来存储内存映射文件中的信息。 #pragma pack(1) typedef struct SHAREDMEMORY_API Data { public: int getKind() { return kind; } int getCountry() { return country; } int getExtra() { return extra; } char* getName(){ printf("Get name value in struct: %s\n", name); return name; } void setKind(int sKind) { kind = sKind; } void setCountry(int scountry) { country = scountry; } void setName(char* sname){ name = new char[strlen(sname)]; strcpy(name, sname); } void deletePointer(){ delete[] name; delete[] type; delete[] band; } private: int kind; int country; int extra; char* name; }; 这些是我在DLL中暴露的方法,以便我的C++ exe和cexe可以调用.< /p> extern "C" void SetData( int kind, int country, int extra, char* name) { CMutex mutex; int size = 1; Data* dynamicArray = new Data[size]; if(m_pViewMMFFile) { Data* record = (Data*) m_pViewMMFFile; // Maps the memory mapped file as an Data object array for (int i = 0; i < size; i++) { dynamicArray[i].setKind(kind); printf("setKind: %i\n", kind); dynamicArray[i].setCountry(country); printf("setCountry: %i\n", country); dynamicArray[i].setExtra(extra); printf("setExtra: %i\n", extra); dynamicArray[i].setName(name); printf("setName: %s\n", name); record[i] = dynamicArray[i]; } record = dynamicArray; delete[] dynamicArray; } mutex.~CMutex(); }_C#_C++_Dll_Pinvoke_Marshalling - Fatal编程技术网 extern "C" void SetData( int kind, int country, int extra, char* name) { CMutex mutex; int size = 1; Data* dynamicArray = new Data[size]; if(m_pViewMMFFile) { Data* record = (Data*) m_pViewMMFFile; // Maps the memory mapped file as an Data object array for (int i = 0; i < size; i++) { dynamicArray[i].setKind(kind); printf("setKind: %i\n", kind); dynamicArray[i].setCountry(country); printf("setCountry: %i\n", country); dynamicArray[i].setExtra(extra); printf("setExtra: %i\n", extra); dynamicArray[i].setName(name); printf("setName: %s\n", name); record[i] = dynamicArray[i]; } record = dynamicArray; delete[] dynamicArray; } mutex.~CMutex(); },c#,c++,dll,pinvoke,marshalling,C#,C++,Dll,Pinvoke,Marshalling" /> extern "C" void SetData( int kind, int country, int extra, char* name) { CMutex mutex; int size = 1; Data* dynamicArray = new Data[size]; if(m_pViewMMFFile) { Data* record = (Data*) m_pViewMMFFile; // Maps the memory mapped file as an Data object array for (int i = 0; i < size; i++) { dynamicArray[i].setKind(kind); printf("setKind: %i\n", kind); dynamicArray[i].setCountry(country); printf("setCountry: %i\n", country); dynamicArray[i].setExtra(extra); printf("setExtra: %i\n", extra); dynamicArray[i].setName(name); printf("setName: %s\n", name); record[i] = dynamicArray[i]; } record = dynamicArray; delete[] dynamicArray; } mutex.~CMutex(); },c#,c++,dll,pinvoke,marshalling,C#,C++,Dll,Pinvoke,Marshalling" />

C# DLL中CARR*的结构值从C++到C节(编组/ pJoCKE) 我现在有一个DLL,它有一个结构,我声明它将被C和C++应用程序用来存储内存映射文件中的信息。 #pragma pack(1) typedef struct SHAREDMEMORY_API Data { public: int getKind() { return kind; } int getCountry() { return country; } int getExtra() { return extra; } char* getName(){ printf("Get name value in struct: %s\n", name); return name; } void setKind(int sKind) { kind = sKind; } void setCountry(int scountry) { country = scountry; } void setName(char* sname){ name = new char[strlen(sname)]; strcpy(name, sname); } void deletePointer(){ delete[] name; delete[] type; delete[] band; } private: int kind; int country; int extra; char* name; }; 这些是我在DLL中暴露的方法,以便我的C++ exe和cexe可以调用.< /p> extern "C" void SetData( int kind, int country, int extra, char* name) { CMutex mutex; int size = 1; Data* dynamicArray = new Data[size]; if(m_pViewMMFFile) { Data* record = (Data*) m_pViewMMFFile; // Maps the memory mapped file as an Data object array for (int i = 0; i < size; i++) { dynamicArray[i].setKind(kind); printf("setKind: %i\n", kind); dynamicArray[i].setCountry(country); printf("setCountry: %i\n", country); dynamicArray[i].setExtra(extra); printf("setExtra: %i\n", extra); dynamicArray[i].setName(name); printf("setName: %s\n", name); record[i] = dynamicArray[i]; } record = dynamicArray; delete[] dynamicArray; } mutex.~CMutex(); }

C# DLL中CARR*的结构值从C++到C节(编组/ pJoCKE) 我现在有一个DLL,它有一个结构,我声明它将被C和C++应用程序用来存储内存映射文件中的信息。 #pragma pack(1) typedef struct SHAREDMEMORY_API Data { public: int getKind() { return kind; } int getCountry() { return country; } int getExtra() { return extra; } char* getName(){ printf("Get name value in struct: %s\n", name); return name; } void setKind(int sKind) { kind = sKind; } void setCountry(int scountry) { country = scountry; } void setName(char* sname){ name = new char[strlen(sname)]; strcpy(name, sname); } void deletePointer(){ delete[] name; delete[] type; delete[] band; } private: int kind; int country; int extra; char* name; }; 这些是我在DLL中暴露的方法,以便我的C++ exe和cexe可以调用.< /p> extern "C" void SetData( int kind, int country, int extra, char* name) { CMutex mutex; int size = 1; Data* dynamicArray = new Data[size]; if(m_pViewMMFFile) { Data* record = (Data*) m_pViewMMFFile; // Maps the memory mapped file as an Data object array for (int i = 0; i < size; i++) { dynamicArray[i].setKind(kind); printf("setKind: %i\n", kind); dynamicArray[i].setCountry(country); printf("setCountry: %i\n", country); dynamicArray[i].setExtra(extra); printf("setExtra: %i\n", extra); dynamicArray[i].setName(name); printf("setName: %s\n", name); record[i] = dynamicArray[i]; } record = dynamicArray; delete[] dynamicArray; } mutex.~CMutex(); },c#,c++,dll,pinvoke,marshalling,C#,C++,Dll,Pinvoke,Marshalling,这就是我试图用C语言进行编组的地方 class Program { [DllImport("MemoryMapDLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] extern static void SetData( [MarshalAs(UnmanagedType.I4)] int kind, [MarshalAs(UnmanagedTyp

这就是我试图用C语言进行编组的地方

class Program
{
    [DllImport("MemoryMapDLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    extern static void SetData(
        [MarshalAs(UnmanagedType.I4)] int kind,
        [MarshalAs(UnmanagedType.I4)] int country,
        [MarshalAs(UnmanagedType.I4)] int extra,
        [MarshalAs(UnmanagedType.LPStr)] string name
        );

    [DllImport("MemoryMapDLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    extern static IntPtr GetData();

    private void UdpMessageSending(string inputMessage)
    {
        UdpClient udpClient = new UdpClient(11000);
        udpClient.Connect("127.0.0.1", 11000);
        Console.WriteLine("Sending UDP Message: " + inputMessage);
        // Sends a message to the host to which you have connected.
        Byte[] sendBytes = Encoding.ASCII.GetBytes(inputMessage);
        udpClient.Send(sendBytes, sendBytes.Length);
        udpClient.Close();
    }

    static void Main(string[] args)
    {
        try
        {
            for (; ;)
            {
               string x = Console.ReadLine();

               Program p = new Program();
               p.UdpMessageSending("Play");

               //SetData(1, 2, 225, 2, type, 4, 1, 0, name, 1, 4, band);

               Thread.Sleep(1000);

               IntPtr ptr = GetData();
               Console.WriteLine("Pointer: " + ptr.ToString());


               MarshalClass.Data data = (MarshalClass.Data)Marshal.PtrToStructure(ptr, typeof(MarshalClass.Data));
               Console.WriteLine("Data Size in C#: " + Marshal.SizeOf(typeof(MarshalClass.Data)));

               Console.WriteLine("Kind: " + data.kind);
               Console.WriteLine("Country: " + data.country);
       Console.WriteLine("Extra: " + data.extra);
       IntPtr nameIntPtr = data.name;
               Console.WriteLine("NameIntPtr: " + nameIntPtr);

               string name = Marshal.PtrToStringAnsi(nameIntPtr);
               if (name != null)
               {
        Console.WriteLine("Name: " + name);
               }
            }
        }
        catch (Exception exception)
        {
            Console.WriteLine("Error");
            Console.WriteLine("===============================================");
            Console.WriteLine(exception.ToString());
        }
    }
}
}


当我试图检索C端的信息时,问题出现了。它无法检索char*name属性。当它试图调用DLL中的GetData方法时,会抛出AccessViolationException错误并使我的应用程序崩溃,这就是这种情况。但是,它能够检索整数类型的其他属性,没有任何问题。如果我试图在C和C中设置数据,那么它会完全恢复,但当我的C++应用程序试图检索char *名称时,应用程序就会崩溃。然而,在我的DLL中,我能够打印出存储的名称数据的地址,因此消除了它为空的可能性。那么,可能的原因是什么呢?有人知道解决这个问题的方法吗?

这是从一个大错误开始的,setName函数有一个off by one错误。它必须分配strlensname+1字节,为零终止符额外分配一个字节。这导致的堆损坏只会让程序陷入无法察觉的痛苦漩涡,当您使用pinvoke时,调试难度会增加十倍。无法可靠地释放分配给数据的内存只会让情况变得更糟。我已经对代码进行了重大更改,采纳了您给出的建议,我使用固定大小的字符数组而不是字符指针,现在工作正常。谢谢你的评论!
using System;
using System.Collections.Generic;

    class MarshalClass
    {
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public class Data
        {
            public Int32 kind;

            public Int32 country;

            public Int32 extra;

            public IntPtr name;
        }
      }
    }
class Program
{
    [DllImport("MemoryMapDLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    extern static void SetData(
        [MarshalAs(UnmanagedType.I4)] int kind,
        [MarshalAs(UnmanagedType.I4)] int country,
        [MarshalAs(UnmanagedType.I4)] int extra,
        [MarshalAs(UnmanagedType.LPStr)] string name
        );

    [DllImport("MemoryMapDLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    extern static IntPtr GetData();

    private void UdpMessageSending(string inputMessage)
    {
        UdpClient udpClient = new UdpClient(11000);
        udpClient.Connect("127.0.0.1", 11000);
        Console.WriteLine("Sending UDP Message: " + inputMessage);
        // Sends a message to the host to which you have connected.
        Byte[] sendBytes = Encoding.ASCII.GetBytes(inputMessage);
        udpClient.Send(sendBytes, sendBytes.Length);
        udpClient.Close();
    }

    static void Main(string[] args)
    {
        try
        {
            for (; ;)
            {
               string x = Console.ReadLine();

               Program p = new Program();
               p.UdpMessageSending("Play");

               //SetData(1, 2, 225, 2, type, 4, 1, 0, name, 1, 4, band);

               Thread.Sleep(1000);

               IntPtr ptr = GetData();
               Console.WriteLine("Pointer: " + ptr.ToString());


               MarshalClass.Data data = (MarshalClass.Data)Marshal.PtrToStructure(ptr, typeof(MarshalClass.Data));
               Console.WriteLine("Data Size in C#: " + Marshal.SizeOf(typeof(MarshalClass.Data)));

               Console.WriteLine("Kind: " + data.kind);
               Console.WriteLine("Country: " + data.country);
       Console.WriteLine("Extra: " + data.extra);
       IntPtr nameIntPtr = data.name;
               Console.WriteLine("NameIntPtr: " + nameIntPtr);

               string name = Marshal.PtrToStringAnsi(nameIntPtr);
               if (name != null)
               {
        Console.WriteLine("Name: " + name);
               }
            }
        }
        catch (Exception exception)
        {
            Console.WriteLine("Error");
            Console.WriteLine("===============================================");
            Console.WriteLine(exception.ToString());
        }
    }
}