0

首先,我要感谢马特戴维斯的这篇文章。我知道该帖子未被选为该特定问题的答案,但该帖子对我非常有帮助。我有几个小问题需要解决(主要是调整他提供的代码中的文件路径),但我很容易使用他的 C++ 桥接方法为 C# WCF 服务创建非托管 C++ 客户端。

我现在正在探索如何改进那里提出的基本概念。以下是 Matt 帖子中 HelloServiceClientBridge.cpp 文件中的一些代码:

String^ message = client->SayHello(gcnew String(name)); 
client->Close(); 
IntPtr ptr = Marshal::StringToHGlobalAnsi(message); 
rv = std::string(reinterpret_cast<char *>(static_cast<void *>(ptr)));

似乎要在这里创建很多字符串的副本。以下是我看到的可能制作字符串副本的所有潜在位置:

  • name变量中字符串的原始非托管副本
  • gcnew String(name)调用时字符串的托管副本
  • 我不确定,但是当托管字符串作为参数传递给SayHello()方法时,可能会创建另一个副本
  • 该字符串被复制到发送到 C# 服务的 WCF 消息中
  • 我不确定,但 C# 服务在收到消息时可能会创建另一个副本
  • String.Format我认为调用时会创建另一个字符串副本
  • 新的“Hello”字符串被复制到发送给客户端的 WCF 消息中
  • 我不确定,但 C# 客户端在收到消息时可能会创建另一个副本
  • 我不确定,但是当 C# 客户端将字符串返回到 C++ 桥时,可能会创建另一个副本
  • Marshal::StringToHGlobalAnsi(message)调用时会创建新字符串的非托管副本
  • 我不确定,但是当字符串转换为std::string

现在,我意识到当我们使用非托管和托管互操作和进程间通信时,一些复制是不可避免的,但我想知道是否可以避免一些这种复制。对于简单的 HelloWorld 类型示例来说,这没什么大不了的,但是如果要传递大量数据,则从非托管复制到托管然后再从一个进程复制到另一个进程的成本可能会很大。所以,我想知道是否有一种方法可以在进程间通信发生的同时进行从非托管到托管和/或反之的编组。

我考虑的一种可能性是修改代码,以便可以将字符串从非托管字符串直接复制到格式化为托管字符串的 WCF 消息中。我想既然我们无论如何都必须制作一个副本,那么如果该副本也可以提供早期副本之一的功能,那就太好了,这样我们就可以用一块石头杀死两只鸟。

我考虑的另一种可能性是通过 WCF 消息将非托管指针从 C++ 进程传递到 C# 服务,然后该消息可以由 C# 服务编组为托管字符串。当然,确定谁负责为该指针分配内存和解除分配内存可能会很麻烦,但是复制会减少,WCF 消息的大小也会显着减少。

感谢您的任何想法!

4

1 回答 1

0

我已经开始探索 WWSAPI 作为一种为 WCF 服务创建 C++ 客户端的方法。到目前为止,看起来这个解决方案运行良好。

于 2010-01-15T13:51:08.360 回答