0

所以,我正在尝试以 64 位模式运行我的 .NET 应用程序。我依赖于可以为 x64 编译的 dll 并且它可以正确加载。我可以调用一些调用,但是当我尝试调用特定调用时,应用程序会完全崩溃。没有错误或任何东西......

错误发生在两个地方之一;要么在这里:

#include "socket.h"
int SenderAddrSize = sizeof(SOCKADDR_IN);
SOCKADDR_IN CSocket::SenderAddr;

...

char* CSocket::tcpip()
{
if(sockid<0)return NULL;
if(getpeername(sockid, (SOCKADDR *)&SenderAddr, &SenderAddrSize) == SOCKET_ERROR)return NULL;
return inet_ntoa(SenderAddr.sin_addr);
}

...

或在这里:

#include "buffer.h"
char CBuffer::retval[20001];
CBuffer::CBuffer()
{
BuffSize = 30;
data = (char*)malloc(BuffSize);
count = 0;
readpos = 0;
writepos = 0;
}

...

你可以在我的 GitHub HEREsocket.cppbuffer.cpp中找到完整的代码。代码的入口点和调用上述方法的对象都位于 main.cpp

p/invoke 调用如下:

对于插座:

[DllImport("SockLib", CallingConvention = CallingConvention.Cdecl, EntryPoint = "tcpip")]
public static extern String tcpip(Double socket);

对于缓冲区:

 [DllImport("SockLib", CallingConvention = CallingConvention.Cdecl, EntryPoint = "createbuffer")]
 public static extern Double createbuffer();

为什么代码崩溃的任何想法。这在 x86 中就像一个魅力,只是在 x64 中没有......

另外,作为一个附带问题...如果我将一个 int 写入在 x86 中运行的客户端上的缓冲区并在 x64 服务器上接收它(反之亦然),该 int 是 4 字节还是 8 字节?关键字int是否会因平台特定大小而改变,还是必须指定int64才能获得 8 字节整数?这适用于上述较大问题的 C++ 源代码部分。

4

1 回答 1

2

不要string在 ap/invoke 调用中用作返回值。这将假设内存是使用分配的CoTaskMemAlloc,因此将导致编组器调用CoTaskMemFree返回的指针。这会导致运行时错误。

一种选择是您可以更改本机代码以CoTaskMemAlloc用于将其分配的内存返回给 C#。如果你这样做了,那么你可以继续使用string你的 p/invoke 返回值。

另一种方法是malloc像现在一样IntPtr在 C# 端使用,并从您的本机代码中导出释放器。

要从转换IntPtr为字符串,请使用Marshal.PtrToStringAnsi(). 完成后,您可以将指针传递回您的本机 DLL,以便它可以调用free()它。

看起来像这样:

[DllImport("SockLib", CallingConvention=CallingConvention.Cdecl)]
public static extern IntPtr tcpip(double socket);

你这样称呼它:

IntPtr strPtr = tcpip(socket);
string str = Marshal.PtrToStringAnsi(strPtr);

您需要对每个返回字符串的 p/invoke 调用执行类似的操作。

您是否需要释放这些指针并不是 100% 清楚的。这取决于您是否在 C++ 代码中分配了内存。例如,tcpip映射到对 的调用inet_ntoa。这将返回一个指向套接字库拥有的缓冲区的指针。所以你的代码不能试图释放它。malloc但是,如果您返回使用or分配的内存new[],那么您也必须释放它。


其他一些观察:

  • 您正在返回在 C++ 代码中声明但在 C 包装器中int键入它们的 套接字。double不要那样做。一直使用int
  • C# 类型int为 32 字节。对于 64 位整数,请使用long. 未签名版本是uintulong。对于机器字长的类型,请使用IntPtrUIntPtr
于 2012-10-18T08:08:44.807 回答