我正在使用C#和WCF进行两个过程,第二个过程和wwsapi在第二个过程中编写。我希望能够定义用于单个位置两者之间的通信的地址,并同时使用c#和C ++使用它。这可能吗?

我最接近的是定义IDL中的常数,然后使用MIDL和TLBIMP将其放入C#可以消耗的DLL中。但是,这似乎并没有暴露出常数,或者至少我不知道如何做到这一点。也许仅限于键入定义。

还有其他建议吗?

有帮助吗?

解决方案

C#和C ++具有不同的常数模型。通常,该常数甚至不会在生成的C ++二进制中发射 - 在大多数情况下,它会自动替换在需要的地方。

而不是使用常数,而是制作返回常数的函数,您可以从C#调用该函数。

因此,

#include <iostream>
const double ACCELERATION_DUE_TO_GRAVITY = 9.8;
int main()
{
     std::cout << "Acceleration due to gravity is: " << 
         ACCELERATION_DUE_TO_GRAVITY;
}

变成

#include <iostream>
extern "C" double AccelerationDueToGravity()
{
    return 9.8;
}
int main()
{
     std::cout << "Acceleration due to gravity is: " << 
         AccelerationDueToGravity();
}

您应该可以从C#调用。

其他提示

您可以创建一个单独的C ++/CLI项目,并在A中定义所有常数 .h 文件。例如,创建名为“ ConstantBridge”的C ++/CLI类库项目和一个名为“ CSHARPPROGRAM”的C#项目:

常数

namespace Constants
{
    const int MAGIC_NUMBER = 42;
}

// String literals must be defined as macros
#define MAGIC_PHRASE "Hello World"

// Since stirngs must be macros it's arguably more consistent 
// to use `define` throughout. This is for demonstration purpose.

恒定桥

#include "Constants.h"

namespace ConstantBridge { public ref class ConstantBridge {
public:
    // The use of the `literal` keyword is important
    // `static const` will not work
    literal int kMagicNumber = Constants::MAGIC_NUMBER;
    literal String ^ kMagicPhrase = MAGIC_PHRASE;
};}

csharpprogram.cs

Console.WriteLine(ConstantBridge.kMagicNumber); // "42"
Console.WriteLine(ConstantBridge.kMagicPhrase); // "Hello World"

现在,具有“ CSHARPPROGRAM”项目参考“ ConstantBridge”项目。您的其他本地C ++项目可以简单地 #include "Constants.h".

只要您参考 只要 literal来自 ConstantBridge 项目,将不会生成运行时依赖关系。您可以使用 ilspy 或iLdasm。 const 在C#和 literal 在C ++/CLI中是 将“字面上的”复制到呼叫网站 在汇编期间。

对我的用例不满意的其他解决方案,因此编码了一个稍微适合原始请求的稍微削减的解决方案; 一个可以内置到一个文件中的常数 两个都 一个C#和C ++项目...

  1. .cs文件中的版本信息,在公共位置。

像这样:

// Version.cs
public static class MyAppVersion
{
    //build
    public static string Number = "1.0";
    public static string Phase = "Alpha";

    //configuration (these are the build constants I use, substitute your own)
#if BUILD_SHIPPING
    public static string Configuration = "Shipping";
#elif BUILD_DEVELOPMENT
    public static string Configuration = "Development";
#elif BUILD_DEBUG
    public static string Configuration = "Debug";
#else
    "build type not defined"
#endif
}
  1. 使用添加现有项目在C#项目中包括... [添加AS链接
  2. 在C ++项目(在.cpp文件中)中包含一个 #include

像这样:

//include version information into a .cpp
#define class namespace
#define public
#define static
#define string const char*
#include "..\..\Version.cs" //or to where-ever your file is
;
#undef class
#undef public
#undef static
#undef string
  1. 在C#中引用: MyAppVersion.Number
  2. 在C ++中引用: MyAppVersion::Number

过去,我不得不做这些事情时,我只是在构建过程中添加了一个额外的预编译步骤,该过程自动从另一个文件中创建一个文件。

由于您的常数可能会在C#中的类中,因此您可以将其用作源文件:

MyClass.cs:
    class MyClass {
        public const int NUM_MONTHS = 12;    //COMMON
        public const int YEAR_BASE = 1900;   //COMMON
    }

grep '//COMMON' MyClass.cs
    | sed -e 's/^ *public const [a-z][a-z]*/#define/'
          -e 's/ *= */ /'
          -e 's/;.*$//'
    >MyClass.h
grep '//COMMON' MyClass.cs | sed -e 's/ *public //' -e 's/;.*$/;/' >MyClass.hpp

这将为您提供:

MyClass.h:
    #define NUM_MONTHS 12
    #define YEAR_BASE 1900

MyClass.hpp:
    const int NUM_MONTHS = 12;
    const int YEAR_BASE = 1900;

现在,让Visual Studio执行该步骤不是我知道该怎么做的事情。您必须调查是否有可能。 Unixy的文本处理工具确实值得下载。我有 cygwin 安装在几个盒子上,但是,对于本地化的东西,您可以摆脱个人 GNUWIN32软件包.

您可能在Powershell上做类似的工作,但我并不是很精通。


现在,这有点笨拙,所以我可以为您的特定问题建议一种更好的方法。别 采用 一个常数。将地址放入配置文件中,并在启动时将其C#和C ++代码读取。

这样,您就可以毫不痛苦地分享价值 如果您想将来更改它,它是可配置的。

对于每个常数的方法,可以更轻松的替代方法是包含常数为实例属性的类。您可以在C#中创建它,并通过COM接口将其暴露于C ++。这比P/Invoke更容易且容易出错,因为您不必担心正确地获取所有类型和名称 - 编译器为您完成了所有类型和名称。

注意:我没有尝试过,我只是猜测 应该 工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top