C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[17]: C#でC++DLLコマンドを実行


(過去ログ 161 を表示中)

[トピック内 20 記事 (1 - 20 表示)]  << 0 >>

■92947 / inTopicNo.1)  C#でC++DLLコマンドを実行
  
□投稿者/ サラリーマンZ (3回)-(2019/11/11(Mon) 17:23:08)

分類:[C#] 

2019/11/11(Mon) 17:23:32 編集(投稿者)
C#プログラムでC++のDLLからコマンドを呼び出して動作させようとしております。
C++DLLをC#で呼び出すところは全くの初心者です。ご承知置き下さい。

DLLのコマンド Connect は2つのPC間を通信させる内容になっており、
Connect () の中身は 2つのPCそれぞれのIPアドレスを32ビット形式、そしてそれぞれのポート番号を
入れるようになっています。

C++ DLL の実行コマンド↓

Connect(struct ConnectParameter)

struct ConnectParameter
 char Addr1[32]  例 192.168.1.1
 char Addr2[32]  例 192.168.1.2
 unsigned int Port1  例 9999
 unsigned int Port2  例 9999

C++DLLのコマンドを実行させるための32ビット形式のchar型に対して
C#ではどの型で対応していいかよく分からなかったので
単純にstring形式でIPアドレスを入力、int形式でポート番号を入力、
としてしまいましたが、本来であればどのようにしたら良いのでしょうか?
どなたかご助言、お願い致します。


C# プログラム↓

public string Addr1;
public string Addr2;
public int Port1;
public int Port2;

//入力
Addr1 = "192.168.1.1".ToString();
Addr2 = "192.168.1.2".ToString();
Port1 = 9999;
Port2 = 9999;

//実行
Connect(Addr1, Addr2, Port1, Port2);

引用返信 編集キー/
■92948 / inTopicNo.2)  Re[1]: C#でC++DLLコマンドを実行
□投稿者/ Hongliang (913回)-(2019/11/11(Mon) 17:37:16)
> 32ビット形式のchar型

char Addr1[32]は、要素数32のcharの静的配列です。
静的配列はMarshalAs属性でSizeConstを指定します。

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ConnectParameter
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public string Addr1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public string Addr2;
    public int Port1;
    public int Port2;
}

ざっとこんな感じになります。

ところでC++の
Connect(struct ConnectParameter)
は本当にこのままですか?
* とか & とかが付いていませんか?

引用返信 編集キー/
■92971 / inTopicNo.3)  Re[2]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (4回)-(2019/11/12(Tue) 12:23:28)
Hongliangさん、有難うございます。
早速確認してみます!

C++ のところ、*が付いていました。




No92948 (Hongliang さん) に返信
> > 32ビット形式のchar型
>
> char Addr1[32]は、要素数32のcharの静的配列です。
> 静的配列はMarshalAs属性でSizeConstを指定します。
>
> [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
> public struct ConnectParameter
> {
> [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
> public string Addr1;
> [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
> public string Addr2;
> public int Port1;
> public int Port2;
> }
>
> ざっとこんな感じになります。
>
> ところでC++の
> Connect(struct ConnectParameter)
> は本当にこのままですか?
> * とか & とかが付いていませんか?
引用返信 編集キー/
■93006 / inTopicNo.4)  Re[2]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (5回)-(2019/11/13(Wed) 17:21:56)
Hongliangさんの回答を参考に下記プログラムを作成してみましたが、
うまく通信ができませんでした。↓
要因が今のところ分かりません。

//構造体の宣言
ConnectParameter CP = new ConnectParameter();

//DLL実行コマンドのインポート
[DllImport("ConnectionDLL.dll", CallingConvention = CallingConvention.Cdecl)]
extern static int Connect(ConnectParameter CP);

//CPの中身 入力
CP.Addr1 = "192.168.1.1";
CP.Addr2 = "192.168.1.2";
CP.Port1 = 9999;
CP.Port2 = 9999;

//通信コマンド実行
Connect(CP);



もともと、C++の実行プログラム(↓)でしたら問題なく動作するので
C#プログラム(↑)のところがおかしいような気がするのですが、
どなたか気付かる点、ありましたら教えてください。


	WSADATA wsadata;
	int     rc;

	rc = WSAStartup( 0x0101, &wsadata );
	if( rc != 0 )
	{ return; }

	sprintf_s( CP.Addr1, "%s", "192.168.1.1" );
	CP.Port1 = 9999;
	sprintf_s( CP.Addr2, "%s", "192.168.1.2" );
	CP.Port2 = 9999;

	//ここで入力するとDLLでのエラーを回避できる(DLL内ではコピーするだけ)
	try
	{
		LPHOSTENT PC_lpHost = gethostbyname(CP.Addr1 );
                CP.my.sin_family = AF_INET;    	 
		CP.my.sin_addr = *((LPIN_ADDR*PC_lpHost->h_addr_list);		        CP.my.sin_port = htons( CP.Port1 );

		LPHOSTENT MP_lpHost = gethostbyname(CP.Addr2 );
                CP.dst.sin_family = AF_INET;    	 
		CP.dst.sin_addr = *((LPIN_ADDR*PC_lpHost->h_addr_list);		        CP.dst.sin_port = htons( CP.Port2 );
	}
	catch(...)
	{
		MessageBox::Show( "エラー" );
		return;
	}

	//Open
	int Ans;

	try
	{
		Ans = Connect(CP);
	}
	catch(...)
	{
		Ans = -1;
	}

	//Status
	if( Ans == 0 ) 
	{ 
		MessageBox::Show( "接続 OK" );
	}
	else  
	{ 
		MessageBox::Show( "接続 NG" );
	}

引用返信 編集キー/
■93010 / inTopicNo.5)  Re[3]: C#でC++DLLコマンドを実行
□投稿者/ Hongliang (917回)-(2019/11/13(Wed) 19:16:04)
以前の
> C++ のところ、*が付いていました。
という回答が正しいのであれば、
> Ans = Connect(CP);
はコンパイルエラーになるはずですが。

> CP.my.sin_addr = *((LPIN_ADDR*PC_lpHost->h_addr_list);
この辺のコードも、
> struct ConnectParameter
> char Addr1[32]  例 192.168.1.1
> char Addr2[32]  例 192.168.1.2
> unsigned int Port1  例 9999
> unsigned int Port2  例 9999
と全く相容れません。

C++のConnectParameter構造体とConnect関数の定義をコピー&ペーストで正しく提示してください。
引用返信 編集キー/
■93014 / inTopicNo.6)  Re[4]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (6回)-(2019/11/14(Thu) 08:59:35)
分かりにくくて申し訳ありませんでした。

C++のConnectParameter構造体とConnect関数の定義はこちらになります。

struct ConnectParameter
{
   char  Addr1[32];
   char  Addr2[32];
   unsigned int Port1;
   unsigned int Port2;
   struct sockaddr_in my;
   struct sockaddr_in dst;
   int PLC_Type;
};

Connect(struct ConnectParameter CP);


もともと外部で作製されたC++のDLLだけ提供されており、
それをC#で実行させたいという目的であるため、DLLの中身は上記記載の内容しか
把握できていない状態です。

ただ、C++で動作させるソースコードは提供されている。

Hongliangさん、ご丁寧にご対応頂き感謝しております。


■No93010 (Hongliang さん) に返信
> 以前の
>>C++ のところ、*が付いていました。
> という回答が正しいのであれば、
>>Ans = Connect(CP);
> はコンパイルエラーになるはずですが。
> 
>>CP.my.sin_addr = *((LPIN_ADDR*PC_lpHost->h_addr_list);
> この辺のコードも、
>>struct ConnectParameter
>>char Addr1[32]  例 192.168.1.1
>>char Addr2[32]  例 192.168.1.2
>>unsigned int Port1  例 9999
>>unsigned int Port2  例 9999
> と全く相容れません。
> 
> C++のConnectParameter構造体とConnect関数の定義をコピー&ペーストで正しく提示してください。

引用返信 編集キー/
■93015 / inTopicNo.7)  Re[5]: C#でC++DLLコマンドを実行
□投稿者/ Hongliang (918回)-(2019/11/14(Thu) 10:06:41)
> struct ConnectParameter
> {
>    char  Addr1[32];
>    char  Addr2[32];
>    unsigned int Port1;
>    unsigned int Port2;
>    struct sockaddr_in my;
>    struct sockaddr_in dst;
>    int PLC_Type;
> };
わざわざmy/dstを公開してるということは、
それらも呼び出し側が設定する必要があるということなんでしょうね。
なのでC#でもこれらを定義してConnectParameterに追加する必要があります。
sockaddr_inは以下のような定義になるでしょう。

struct sockaddr_in {
    public ushort sin_family, sin_port;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
    public byte[] sin_addr;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
    public byte[] sin_zero;
}

sin_addrに相当するバイト配列は、IPアドレス限定であれば、
IPAddress.Parse(address).GetAddressBytes()
で取得できます。
名前解決も必要なら、
(1) IPAddress.TryParseして成功ならそのIPAddressを使う
(2) 1に失敗したらDns.GetHostEntryを呼び出し、AddressListの中から、
  AddressFamilyがInterNetworkのIPAddressを使う
という手順が良いかと思います。

// PLC_Typeは設定しなくていいのかな…。

> Connect(struct ConnectParameter CP);
結局
> C++ のところ、*が付いていました。
は勘違いということで良いんですかね?
付いているかどうかで、C#のDllImportするConnect関数の定義も変わってきますが。

引用返信 編集キー/
■93020 / inTopicNo.8)  Re[6]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (7回)-(2019/11/14(Thu) 23:36:23)
Hongliangさん、ご丁寧に回答頂き誠に有難う御座います。
C++ DLL作成者に問い合わせたところ、コマンド実行のために my / dst の指定は必要とのことで、
Hongliangさんご察しの通りでした。

struct sockaddr_inの定義コード有難うございます。
参考にさせていただきます。 ↓下記のようなコードでとりあえず試してみます。

        //ConnectParameterの定義
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct ConnectParameter
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string Addr1;
            public int Port1;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string Addr2;
            public int Port2;
        }

        //sockaddr_inの定義
        struct sockaddr_in
        {
            public ushort sin_family, sin_port;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public byte[] sin_addr;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public byte[] sin_zero;
        }

    //コマンド実行
        private void button1_Click(object sender, EventArgs e)
        {
                CP.Addr1 = "192.168.1.2";
                CP.Port1 = 9999;
                CP.Addr2 = "192.168.1.1";
                CP.Port2 = 9999;

                my.sin_addr = IPAddress.Parse(CP.Addr1).GetAddressBytes();
                dst.sin_addr = IPAddress.Parse(CP.Addr2).GetAddressBytes();

                Connect(CP);
        }

struct sockaddr_in の中身としてsin_family / sin_port / sin_addr / sin_zero とありますが、
sin_addr だけでなく、sin_family や sin_port も指定してあげないと
うまく動作しない感じでしょうか。。。

>>Connect(struct ConnectParameter CP);
> 結局
>>C++ のところ、*が付いていました。
> は勘違いということで良いんですかね?

Connect(struct ConnectParameter CP)に関しては、*付いていませんでした。
勘違いでした。。。 混乱させて申し訳ありません。

引用返信 編集キー/
■93021 / inTopicNo.9)  Re[7]: C#でC++DLLコマンドを実行
□投稿者/ Azulean (1103回)-(2019/11/15(Fri) 06:29:33)
No93020 (サラリーマンZ さん) に返信
> struct sockaddr_in の中身としてsin_family / sin_port / sin_addr / sin_zero とありますが、
> sin_addr だけでなく、sin_family や sin_port も指定してあげないと
> うまく動作しない感じでしょうか。。。

それは第三者にはわからないので、気になるなら DLL 作者に聞いてください。
(C++ のコードも同じようにそのメンバーは存在するのでそこから類推できるのでは…?)
引用返信 編集キー/
■93202 / inTopicNo.10)  Re[8]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (8回)-(2019/11/27(Wed) 22:32:30)
皆様、いろいろアドバイス有難うございました。
結局C#でC++のDLLを読み込んでコマンドを実行させるのがどうしてもうまくいかず、
あきらめてC++のDLLのコマンドを実行させる動作をさせる関数を作って、
その関数をDLLとしてコンパイルして、DLLのコマンドを動作させるためのDLLを作って
そのDLLをC#で実行させようと考えました。

C++ DLLのコマンドを動作させるソースを元に下記のようなコードを書きました↓

source.cpp

#include "Header.h"
#include <stdio.h>
#include <Windows.h>
#include <process.h>
#include <time.h>
#include <fstream>
#include <vcclr.h>//外部ファイル実行用(キャスト)

#include "Drive01.h"
#pragma comment(lib, "Drive01.lib")

ConnectParameter CP;

void Open()
{
WSADATA wsadata;
int rc;

rc = WSAStartup( 0x0101, &wsadata );
if( rc != 0 )
{ return; }

sprintf_s( CP.Addr1, "%s", "192.168.1.1" );
CP.Port1 = 9999;
sprintf_s( CP.Addr2, "%s", "192.168.1.2" );
CP.Port2 = 9999;

LPHOSTENT PC_lpHost = gethostbyname(CP.Addr1 );
CP.my.sin_family = AF_INET;
CP.my.sin_addr = *((LPIN_ADDR*PC_lpHost->h_addr_list);
CP.my.sin_port = htons( CP.Port1 );

LPHOSTENT MP_lpHost = gethostbyname(CP.Addr2 );
CP.dst.sin_family = AF_INET;
CP.dst.sin_addr = *((LPIN_ADDR*PC_lpHost->h_addr_list);
CP.dst.sin_port = htons( CP.Port2 );

//コマンド実行
Connect(CP);
}


header.h

#pragma once
#define DllExport __declspec( dllexport )

extern "C"
{
DllExport void Open();
}


↑この内容でDLLとしてビルドしようとすると、
fatal error C1190: マネージ ターゲット コードには '/clr' が必要です、のエラー内容で
ビルドができませんでした。

vcclr.h の中身を見てみると #using <mscorlib.dll> の構文でエラーが出ていて
using には C++/CLIモードが必要ですと出てしまいます。

具体的にどのように対策したら良いのでしょうか?

vcclr.h の中身みると他にもエラーが出ていて

typedef const System::Char* __const_Char_ptr;
typedef const System::Byte* __const_Byte_ptr;
typedef System::Byte* _Byte_ptr;
typedef const System::String* __const_String_handle;

unsigned offset = System::Runtime::CompilerServices::RuntimeHelpers::OffsetToStringData;

の System ::〜の後に付けられるのはクラス名/名前空間だけです、と表示されてしまいます。




引用返信 編集キー/
■93204 / inTopicNo.11)  Re[9]: C#でC++DLLコマンドを実行
□投稿者/ Azulean (1104回)-(2019/11/27(Wed) 22:59:45)
2019/11/27(Wed) 23:01:06 編集(投稿者)

No93202 (サラリーマンZ さん) に返信
> #include <vcclr.h>//外部ファイル実行用(キャスト)

必要なのですか?
いらないのなら消すだけで良いと思いますが…。


ところで、 No93006 に書かれていた「元の C++」は C++ ではなく、C++/CLI となっていそうな予感です。
根拠としては「MessageBox::Show」と出現しているあたりから。

もし、元のサンプルが C++/CLI であり、かつ C++/CLI 固有の要素も含めて真似して作るのであれば、C++/CLI である必要があります。
引用返信 編集キー/
■93233 / inTopicNo.12)  Re[10]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (9回)-(2019/11/28(Thu) 20:44:17)
Azuleanさん、アドバイス有難うございます。

元のサンプルはC++/CLIでした。C++/CLI固有の要素は含めなくてもいいので
ただ単にC++/CLIのコマンドの1つを実行できるDLLつくればよいので。

#include <vcclr.h> 消しました。
LINK1561 エントリーポイントを定義しなければなりません

と出るので、C++/CLI で作るようになってしまっているということですね。


引用返信 編集キー/
■93235 / inTopicNo.13)  Re[11]: C#でC++DLLコマンドを実行
□投稿者/ Azulean (1106回)-(2019/11/28(Thu) 22:07:33)
No93233 (サラリーマンZ さん) に返信
> 元のサンプルはC++/CLIでした。C++/CLI固有の要素は含めなくてもいいので
> ただ単にC++/CLIのコマンドの1つを実行できるDLLつくればよいので。

書き間違いだと思いますが、「C++/CLI のコマンド(関数)」を呼べるのは「C++/CLI か、C# などの .NET Framework の要素のみ」なので、純粋な C++ から呼べない可能性が高いです。
なので、「単に C++ のコマンド(関数)」ということで合っていますよね?

> LINK1561 エントリーポイントを定義しなければなりません

C++ の DLL をエクスポートするプロジェクトを新たに作って、そちらに移植した方が速いのでは?
ただ、今の進捗具合からすると簡単には終わらない予感がしますが…。
引用返信 編集キー/
■93268 / inTopicNo.14)  Re[12]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (10回)-(2019/12/01(Sun) 16:26:00)
何度も質問してすいません。
C#でC++/CLIのDLLをなんとか読み込んで関数実行させようとしています。

参考にしているC++/CLIプログラムでは ConnectParameter CP; と構造体の名前を定義して
そのCPの構造体の中にさらに sockaddr_in my と sockaddr_in dst の構造体が存在しているようなので
下記のように構造体ConnectParameterの中でsockaddr_in my とsockaddr_in dstの宣言をしたのですが
CP.my.sinaddr = のようにメンバを指定してあげようとすると、アクセスできない保護レベルになっている
というエラーになってしまいます。
構造体の中でさらに構造体を宣言するにはどうしたらよいのでしょうか?


    ConnectParameter CP;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ConnectParameter
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string Addr1;
public int Port1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string Addr2;
public int Port2;

  //sockaddr_inの定義
  struct sockaddr_in
  {
  public ushort sin_family, sin_port;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  public byte[] sin_addr;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  public byte[] sin_zero;
  }

sockaddr_in my;
sockaddr_in dst;

}


    //コマンド実行
private void button1_Click(object sender, EventArgs e)
{
CP.Addr1 = "192.168.1.2";
CP.Port1 = 9999;
CP.Addr2 = "192.168.1.1";
CP.Port2 = 9999;

CP.my.sin_addr = IPAddress.Parse(CP.Addr1).GetAddressBytes();
CP.dst.sin_addr = IPAddress.Parse(CP.Addr2).GetAddressBytes();

Connect(CP);
}
引用返信 編集キー/
■93269 / inTopicNo.15)  Re[13]: C#でC++DLLコマンドを実行
□投稿者/ Azulean (1108回)-(2019/12/01(Sun) 16:57:03)
No93268 (サラリーマンZ さん) に返信
> 何度も質問してすいません。
> C#でC++/CLIのDLLをなんとか読み込んで関数実行させようとしています。

No93268 の質問は、単に C# の言語知識の範囲のように思えますが…。
(C++/CLI やら、DLL やらは関係ないということ)

> そのCPの構造体の中にさらに sockaddr_in my と sockaddr_in dst の構造体が存在しているようなので
> 下記のように構造体ConnectParameterの中でsockaddr_in my とsockaddr_in dstの宣言をしたのですが
> CP.my.sinaddr = のようにメンバを指定してあげようとすると、アクセスできない保護レベルになっている
> というエラーになってしまいます。
> 構造体の中でさらに構造体を宣言するにはどうしたらよいのでしょうか?

型の中のメンバー、入れ子になった型は既定だと private なので、型の外から見えません。
見せたいなら public なり、internal なりをつけてください。

そもそも、コレに関して言えば、構造体の中に定義しなくてもなんとかなる話なので、変に真似しない方が良いのでは?と思います。
引用返信 編集キー/
■93270 / inTopicNo.16)  Re[14]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (11回)-(2019/12/01(Sun) 17:06:49)
Azuleanさん

ご回答有難うございます。

> そもそも、コレに関して言えば、構造体の中に定義しなくてもなんとかなる話なので、変に真似しない方が良いのでは?と思います。

構造体の中で定義しなくてもなんとかなるんでしょうか?
もともとのC++/CLIコードで struct ConnectParameter の中に struct sockaddr_in があったので
構造体の中で定義しなければ読み込めないのかと思っていました。。。
引用返信 編集キー/
■93404 / inTopicNo.17)  Re[15]: C#でC++DLLコマンドを実行
□投稿者/ サラリーマンZ (12回)-(2019/12/10(Tue) 15:50:52)
皆様、たびたび質問してすいません。
C++ DLL開発者にもいろいろ聞いて struct ConnectParameter の sockaddr_in dst , sockaddr_in my も
指定しなくてはいけないことが分かりました。

下記のようなコードを書いてみましたが、通信がうまくできませんでした。

ConnectParameter構造体の中で入れ子になっているsockaddr_in構造体の中身も dst、my それぞれ
下記のように設定しましたが、どうもうまくいかず。

sin_family の設定は C++ 上では AF_INET になっているので、調べると
2 を入力すれば IPv4設定ということなので下記のようにしたのですが・・・ どこかおかしいところありましたらご教授ください。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Net;

namespace WindowsFormsApplication
{
    public partial class Form1 : Form
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct ConnectParameter
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string Addr1;
            public int Port1;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string Addr2;
            public int Port2;

            public struct sockaddr_in
            {
                public ushort sin_family, sin_port;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
                public byte[] sin_addr;
            }

        }

        ConnectParameter CP;

        ConnectParameter.sockaddr_in my;
        ConnectParameter.sockaddr_in dst;

        [StructLayout(LayoutKind.Sequential)]
        internal struct WSAData
        {
            public short wVersion;
            public short wHighVersion;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
            public string szDescription;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
            public string szSystemStatus;
            public short iMaxSockets;
            public short iMaxUdpDg;
            public IntPtr lpVendorInfo;
        }

        [DllImport("wsock32.dll")]
        internal static extern int WSAStartup([In] short wVersionRequested, [Out] out WSAData lpWSAData);

        [DllImport("ConnectionDLL.dll", CallingConvention = CallingConvention.Cdecl)]
        extern static int Connect(ConnectParameter CP);

        public int Ans1;


        public Form1()
        {
            InitializeComponent();

        }

        private void button1_Click(object sender, EventArgs e)
        {
            WSAData dummy;

            int a;

            a = WSAStartup(0x0101, out dummy);

            try
            {
                CP.Addr1 = "192.168.1.2";
                CP.Port1 = 9999;
                CP.Addr2 = "192.168.1.1";
                CP.Port2 = 9999;
             
                my.sin_family = 2;  //AF_INET(IPv4)は2にする?
                my.sin_addr = IPAddress.Parse(CP.Addr1).GetAddressBytes();
                my.sin_port = 9999;

                dst.sin_family = 2;  //AF_INET(IPv4)は2にする?
                dst.sin_addr = IPAddress.Parse(CP.Addr2).GetAddressBytes();
                dst.sin_port = 9999;


                Ans1 = Connect(CP);

            }
            catch (Exception)
            {
            }

            //Open

            if (Ans1 == 0)
            {
                MessageBox.Show("接続できました。");
            }
            else
            {
                MessageBox.Show("接続できませんでした。");
            }

        }

引用返信 編集キー/
■93406 / inTopicNo.18)  Re[16]: C#でC++DLLコマンドを実行
□投稿者/ 774RR (756回)-(2019/12/10(Tue) 16:25:35)
うーん・・・
オイラならその Connect() を C# から直接呼ばないだろう。
C# からもっと簡単に呼べるように工夫した wrapper 関数を C++ 側で別途作って
C# からはその wrapper を呼ぶようにするだろう。
# ってか C# にもソケット系関数があるわけで直接そっちを使うっす。
# 現在 C++ で書いてある Connect() 自体を C# で再実装する。そのほうがきっと後で楽できる。
# でかい struct を値渡ししている C++ 関数って、オイラならそういう実装は絶対しない。

catch(Exception) してるけど
C++ Native コードの中から C# Manage コード向けの例外が飛ばせる気がしないし
たとえ飛んできても握り潰しちゃダメ。後で苦労するのはあなた。
オイラの後輩がこんなコード書いてたらぶん殴りものっす。

引用返信 編集キー/
■93420 / inTopicNo.19)  Re[16]: C#でC++DLLコマンドを実行
□投稿者/ Azulean (1114回)-(2019/12/11(Wed) 07:07:49)
No93404 (サラリーマンZ さん) に返信
> ConnectParameter構造体の中で入れ子になっているsockaddr_in構造体の中身も dst、my それぞれ
> 下記のように設定しましたが、どうもうまくいかず。
(略)
> ConnectParameter CP;
> ConnectParameter.sockaddr_in my;
> ConnectParameter.sockaddr_in dst;
(略)
> [DllImport("ConnectionDLL.dll", CallingConvention = CallingConvention.Cdecl)]
> extern static int Connect(ConnectParameter CP);

こういう風に定義していると、my も dst も Connect に渡せていないので間違っているわけですが…。
すでに助言のあるとおり、IP アドレス 2 つを指定する C か C++ の DLL を別途作って、C# から使う用にした方が良いのでは?
引用返信 編集キー/
■93432 / inTopicNo.20)  Re[17]: C#でC++DLLコマンドを実行
 
□投稿者/ サラリーマンZ (13回)-(2019/12/12(Thu) 08:39:53)
774RRさん

返信、アドバイス有難う御座います。
おっしゃる通りConnect()関数をC#から呼び出すのは大変なので避けたいのですが、
動作させたいハードウェアがこの関数を呼び出さないと動かないように
DLL開発者の方がされているようで。。。




Azuleanさん

アドバイス有難うございます。
> こういう風に定義していると、my も dst も Connect に渡せていないので間違っているわけですが…。
Connectに渡せていないでしょうか?もし渡すとしたらどの様にしたら良いか助言頂けないでしょうか?

お二人の意見参考にして、C++のコードでConnect()関数を簡単に呼び出せるようにした方が良さそうですね。
トライしてみます。

お忙しいところ助言、有難う御座います。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -