私はC#でC ++ライブラリを使用するのは初めてで、C++プログラミング全般も初めてです。DLLの名前が「TestManaged.dll」であるため、「マネージ」コードであると思われるC++コードから構築されたDLLがあります。dll / C ++コードが管理されている/管理されていないかどうかは100%わかりません。
このDLLのクラスとメソッドをコードで使用したいと思いC# windows forms application
ます。このDLLには複数のクラスがあります。のこれらのクラスとそれらのクラス内のメソッドをチェックしたときObject Browser
、それらすべてにPublic
識別子があります。
これまで、このDLLをC#アプリケーションコードの参照に追加しました。私の質問で話すクラスは3つあります:Product
、、。このDLLのさまざまなクラスのオブジェクトを次のように作成できます。ReqStatus
ProductData
Product testCall = new ProductClass();
このDLLで呼び出される別のクラスがありProductData
、次のようにこのクラスのC++コードを取得できます。この場合、ProductData
はC#ではクラスとして表示されObject Browser
ますが、実際にはC++コードでは構造体です。これが私の質問に答えるために重要かどうかはわかりません(最後に)。
ProductData
以下は、 struct-- ProductData.h
fileを定義するC++コードです。
#ifdef WIN32_MANAGED
public ref struct ProductData
#else
struct ProductData
#endif
{
UINT32 ProductId; //!< Product ID
UINT32 PRoductRev; //!< Build Revision
};
ReqStatus
以下は、 enum-- ReqStatus.h
fileを定義するC++コードです。識別子を指定せずに、C#コードで同じ列挙型を作成しました。
enum ReqStatus
{
SUCCESS, //!< Method was successful
//Connection errors
NOT_CONNECTED, //!< Connection not open
CONN_TIMEOUT, //!< Connection timed out commuincating with device
};
今、私が呼び出したい2つのメソッドがあり、両方に問題があります。
メソッド1:は、型のオブジェクトをパラメーターとして受け取り、C++の列挙型であるを返すクラスgetProductData
内のメソッドです。したがって、以下はメソッドの宣言です(に見られるように):Product
ProductData
ReqStatus
gerProductData
Object Browser
public ReqStatus getProductData(ProductData data)
同じメソッドのC++の削除は次のとおりです:(実際のメソッドは長すぎるため、宣言を与えるだけです):このメソッドはProdcut.cpp
ファイル内にあります
ReqStatus Product::getProductData(ProductData PLATFORM_PTR data)
PLATFORM_PTRは、以下のように定義されています。Platform.h
#ifdef WIN32_MANAGED
#define PLATFORM_PTR ^
#else
#define PLATFORM_PTR *
#endif
メソッド2:は、文字配列(これはわかりません)とタイプのオブジェクトをパラメーターとして受け取り、C++の列挙型であるを返すクラスgetConnected
内のメソッドです。したがって、以下はメソッドの宣言です(に見られるように):Product
ProductData
ReqStatus
getConnected
Object Browser
public ReqStatus getConnected(sbyte* someChar, ProductData data)
同じメソッドのC++の削除は次のとおりです:(実際のメソッドは長すぎるため、宣言を与えるだけです):このメソッドはProdcut.cpp
ファイル内にあります
ReqStatus Product::getConnected(const char *someChar, ProductData PLATFORM_PTR data)
C ++コードは、次のようにメソッドを呼び出します。
private : Product^ _testProduct;
testProduct = gcnew Product();
ProductData ^ data = gcnew ProductData();
int portNum = Decimal::ToInt16(7);
char portName[32];
_snprintf(&portName[0], sizeof(portName),"COM%d", portNum);
ReqStatus status = _testProduct->getConnected(&portName[0], data); //Calling getConnected
getProductData
メソッド内にメソッドへの内部呼び出しがありgetConnected
ます。
ReqStatus status = getProductData(data); //data is the same which was passed to the getConnected method
私のC#コードは次のとおりで、両方のメソッド呼び出しでエラーが発生しました。以下のコードスニペットの同じ行にエラーを配置しました。どちらの方法も独立しています。それは、C++コードのメソッドgetProductData
から呼び出されるということだけです。getConnected
両方を個別に呼び出すことができるかどうかを確認したかった。
ProductData pData = new ProductData(); // OK
Product _testProduct = new Product(); // OK
ReqStatus status1 = _testProduct.getConnected("COM5", pData ); //Error 1: The best overloaded method getConnected has some invalid arguments
ReqStatus status2 = (ReqStatus)_testProduct.getProductData(pData ); // Error 2: Method is inaccessible due to its protection level
エラー1については、StackOverflowや他のフォーラムのさまざまな記事の解決策を試しましたが、解決できませんでした。参考までに、「SomePortCOM」を次のように変更してみましたが、うまくいきません。
更新:このコードは現在正常に機能しており、エラー1(無効な引数)は表示されません。これで、エラー2(保護レベルのエラー)を取り除くだけで済みます。何か提案をお願いします。ありがとうございました。
String str = "COM5";
byte[] bytes = Encoding.ASCII.GetBytes(str);
unsafe
{
fixed (byte* p = bytes)
{
sbyte* sp = (sbyte*)p;
//SP is now what you want
ReqStatus status1 = _testProduct.getConnected(sp, pData );
}
}
Error2の場合、非常に多くのブログを検索し、考えられる解決策の1つがDLLImportの使用である可能性があることを発見しました。それも試してみましたが、次の問題があります。
DLLImportのC#宣言:
[DllImport("TestManaged.dll",EntryPoint="getConnected")]
public static extern ReqStatus getConnected(String SerialPort, ref ProductData pData);
この関数をC#コードから次のように呼び出しています。
ProductData pData = new ProductData();
String str = "COM7";
ReqStatus status1 = getConnected(str, ref pData);
ただし、Entry point not found
エラーが発生します。このDLLによってエクスポートされた関数のリストを取得するために、dumpbin関数を実行しようとしました。しかし、機能は見当たりません。むしろ、以下のようにランダムな出力です。
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Rumit\TestManaged.dll
File Type: DLL
Summary
2000 .data
22000 .rdata
1000 .reloc
1000 .rsrc
13000 .text
更新:また、DependencyWalkerを介してこのDLLにメソッドが表示されません。これで、C++のソースコードを入手できました。しかし、私はC++コーディングにかなり慣れていません。C ++コードに変更が必要な場合は、指示を教えてください。
よろしく、ルミット