如何在 C# 和 C++ 之间共享常量代码?
我正在编写两个进程,第一个进程使用 C# 和 WCF,第二个进程使用 C++ 和 WWSAPI。我希望能够在一个地方定义用于两者之间通信的地址,并让 C# 和 C++ 都使用它。这可能吗?
我最接近的是在 IDL 中定义常量,然后使用 MIDL 和 TLBIMP 将其放入可由 C# 使用的 DLL 中。然而,这似乎并没有暴露常量,或者至少我不知道如何让它这样做。也许它仅限于类型定义。
还有其他建议吗?
I'm writing two processes using C# and WCF for one and C++ and WWSAPI for the second. I want to be able to define the address being used for communication between the two in a single place and have both C# and C++ use it. Is this possible?
The closest I've come is defining the constant in an IDL, then using MIDL and TLBIMP to get it into a DLL that can be consumed by C#. However this doesn't seem to expose the constant, or at least I can't figure out how to make it do so. Maybe it is limited to type definitions only.
Any other suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以创建一个单独的 C++/CLI 项目并在
.h
文件中定义所有常量。例如,创建名为“ConstantBridge”的 C++/CLI 类库项目和名为“CSharpProgram”的 C# 项目:Constants.h
ConstantBridge.h
CSharpProgram.cs
现在,让“CSharpProgram”项目引用“ConstantBridge”项目。您的其他本机 C++ 项目只需
#include "Constants.h"
即可。只要您仅引用
ConstantBridge
项目中的literal
,就不会生成运行时依赖项。您可以使用 ILSpy 或 ILdasm 进行验证。 C# 中的const
和 C++/CLI 中的literal
在编译期间按字面意思复制到调用站点。You can create a separate C++/CLI project and define all your constants in a
.h
file. For example, create C++/CLI Class Library project called "ConstantBridge" and a C# project called "CSharpProgram":Constants.h
ConstantBridge.h
CSharpProgram.cs
Now, have the "CSharpProgram" project reference the "ConstantBridge" project. Your other native C++ projects can simply
#include "Constants.h"
.As long as you reference only
literal
s from theConstantBridge
project, a runtime dependency will not be generated. You can verify using ILSpy or ILdasm.const
in C# andliteral
in C++/CLI are copied "literally" to the call site during compilation.对我的用例的其他解决方案不满意,因此编写了一个稍微有点hacky的解决方案,似乎更适合原始请求; 一个文件中的常量,可以同时构建到 C# 和 C++ 项目中...
像这样:
#include
包含在 C++ 项目中(在 .cpp 文件中)像这样:
MyAppVersion::Number
Wasn't happy with the other solutions for my use case so coded up a slightly hacky solution that seems to fit the original request better; a constant in one file that can be built into both a C# and a C++ project...
Like this:
#include
Like this:
MyAppVersion.Number
MyAppVersion::Number
C# 和 C++ 对于常量有不同的模型。通常,该常量甚至不会在生成的 C++ 二进制文件中发出——大多数时候它会在需要的地方自动替换。
不要使用常量,而是创建一个返回常量的函数,您可以从 C# 中 P/Invoke 该常量。
因此,
您应该
能够从 C# P/Invoke。
C# and C++ have differing models for constants. Typically, the constant won't even be emitted in the resulting C++ binary -- it's automatically replaced where it is needed most of the time.
Rather than using the constant, make a function which returns the constant, which you can P/Invoke from C#.
Thus,
becomes
which you should be able to P/Invoke from C#.
当我过去不得不做这些事情时,我只是在构建过程中添加了一个额外的预编译步骤,该步骤会自动从另一个文件创建一个文件。
由于您的常量可能位于 C# 中的一个类中,因此您可以将其用作源文件:
这将为您提供:
现在,我不知道如何让 Visual Studio 执行该步骤。你必须调查它是否可能。 UNIXy 文本处理工具确实值得下载。我在一些机器上安装了CygWin,但是,对于这种本地化的东西,您可以使用单独的GnuWin32 软件包。
您可能可以在 PowerShell 中完成类似的工作,但我对此不太熟悉。
现在这有点混乱,所以我可以为你的特定问题建议一个可能更好的方法。根本不要使用常量。将地址放入配置文件中,并让 C# 和 C++ 代码在启动时读取它。
这样,您就可以轻松地共享该值,并且它是可配置的,以防您将来想要更改它。
When I've had to do that stuff in the past, I've simply added an extra pre-compilation step to the build process which automagically creates one file from another.
Since your constants will probably be within a class in C#, you can use that as the source file:
This will give you:
Now, getting Visual Studio to perform that step is not something I know how to do. You'll have to investigate whether or not it's even possible. The UNIXy text processing tools are really worth downloading. I have CygWin installed on a few boxes but, for something this localised, you could get away with individual GnuWin32 packages.
You could probably do a similar job in PowerShell but I'm not really well versed in that.
Now that's a bit of a kludge so may I suggest a possibly better way for you particular question. Don't use a constant at all. Put the address into a configuration file and have your C# and C++ code read it at startup.
That way, you get to share the value painlessly and it's configurable in case you ever want to change it in future.
每个常量的方法的更简单替代方法可能是包含常量作为实例属性的类。您可以用 C# 创建它并通过 COM 接口将其公开给 C++。这比 P/Invoke 更容易且不易出错,因为您不必担心所有类型和名称是否正确 - 这一切都由编译器为您完成。
注意:我还没有尝试过这个,我只是推测它应该有效。
An easier alternative to a method for each constant may be a class containing the constants as instance properties. You could create it in C# and expose it via COM interfaces to C++. That's easier and less error-prone than P/Invoke, since you don't have to worry about getting all the types and names right - it's all done for you by the compiler.
Note: I have not tried this, I'm only speculating that it should work.