C#とC ++コードの間で定数を共有するにはどうすればよいですか?
-
01-10-2019 - |
質問
C#とWCFを1つとC ++とWWSAPIを2番目に使用して2つのプロセスを作成しています。 1つの場所で2つの間の通信に使用されているアドレスを定義し、C#とC ++の両方に使用できるようにしたいと考えています。これは可能ですか?
私が最も近いのは、IDLで定数を定義し、MidlとTLBIMPを使用してC#で消費できるDLLに入れることです。しかし、これは定数を暴露していないようには見えません。少なくとも、それを行う方法を理解できません。たぶん、それはタイプ定義のみに限定されています。
他に提案はありますか?
解決
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#からp/invokeできるはずです。
他のヒント
別のC ++/CLIプロジェクトを作成し、すべての定数をで定義できます .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.
cuntionbridge.h
#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
sから ConstantBridge
プロジェクト、ランタイム依存関係は生成されません。使用を確認できます ilspy またはイルダム。 const
C#と literal
C ++/CLIでは コールサイトに「文字通り」コピーしました 編集中。
私のユースケースの他のソリューションに満足していなかったので、元のリクエストに適していると思われるわずかにハッキーなソリューションをコーディングしました。 組み込むことができる1つのファイルに定数 両方とも C#およびC ++プロジェクト...
- .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
}
- 既存のアイテムを追加してC#プロジェクトに含める... [リンクとして追加
- 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
- C#の参照:
MyAppVersion.Number
- 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よりも簡単でエラーが発生しやすいです - それはすべてコンパイラによってあなたのために行われています。
注:私はこれを試していません、私はそれを推測しているだけです したほうがいい 仕事。