2008年07月07日
VCのDLLをC#から呼び出すには
VCで作られたDLLを、C#から参照したいときの方法。
構造体をやり取りすると想定して、
その場合の方法は以下のとおり。
--------------------------------------------------------------------------
VC側(DLLとなる側)
--------------------------------------------------------------------------
// 構造体を仮定
typedef struct typstrData{
char strMsg[256];
int sw;
char strStok[128];
int sw2;
}TYPESDATA;
// dll側の領域
static TYPESDATA stockdt[5];
static int stockidx=0;
// DLL側関数の例として以下のような2関数を用意していたとする
// データをDLL側に渡す関数(stock_pushd)
int WINAPI stock_pushd(TYPESDATA *psetdt)
{
if( 4<stockidx) return -1;
memcpy(&stockdt[stockidx++],
psetdt,sizeof(TYPESDATA));
return stockidx;
}
// DLL側からデータを受け取る関数(stock_popd)
int WINAPI stock_popd(TYPESDATA *psetdt)
{
if( 0==stockidx) return -1;
memcpy(psetdt,&stockdt[--stockidx],sizeof(TYPESDATA));
return stockidx+1;
}
--------------------------------------------------------------------------
C#側
--------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
namespace TestCSharp
{
// C#側プログラムで実際に使用するデータ用クラス
public class csData
{
public string message;
public int sw1;
public string Stock;
public int sw2;
public csData(){
message = string.Empty;
sw1=0;
Stock=string.Empty;
sw2=0;
}
}
// C#側で、DLLとやり取りを行うクラス
public class testdllApi
{
//----------------------------------------------------------
//構造体定義
//----------------------------------------------------------
// typedef struct typstrData
// {
// char strMsg[256];
// int sw;
// char strStok[128];
// int sw2;
// }TYPESDATA;
// この構造体と同じレイアウトにするには以下のような記述
[StructLayout(LayoutKind.Sequential)]
public struct dll_TYPESDATA
{
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = (int)256)]
public string strMsg;
public int sw;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = (int)128)]
public string strStok;
public int sw2;
}
//----------------------------------------------------------
// 関数定義
//----------------------------------------------------------
// DLL側の関数を使用できるように定義
[System.Runtime.InteropServices.DllImport("testdll.dll")]
public static extern System.Int32
stock_pushd(ref dll_TYPESDATA psetdt);
[System.Runtime.InteropServices.DllImport("testdll.dll")]
public static extern System.Int32
stock_popd(ref dll_TYPESDATA psetdt);
//----------------------------------------------------------
public testdllApi() { /* コンストラクタ */ }
// C#側ではこのメソッドを使用する(pushd)
public int pushd(csData pdt)
{
dll_TYPESDATA dt = new dll_TYPESDATA);
dt.strMsg = pdt.message;
dt.sw = pdt.sw1;
dt.sw2 = pdt.sw2;
dt.strStok = pdt.Stock;
int nans = stock_pushd(ref dt);
return nans;
}
// C#側ではこのメソッドを使用する(popd)
public int popd(ref csData pdt)
{
dll_TYPESDATA dt = new dll_TYPESDATA();
int nans = stock_popd(ref dt);
pdt.message = dt.strMsg ;
pdt.sw1 = dt.sw;
pdt.sw2 = dt.sw2;
pdt.Stock = dt.strStok;
return nans;
}
}
}
構造体をやり取りすると想定して、
その場合の方法は以下のとおり。
--------------------------------------------------------------------------
VC側(DLLとなる側)
--------------------------------------------------------------------------
// 構造体を仮定
typedef struct typstrData{
char strMsg[256];
int sw;
char strStok[128];
int sw2;
}TYPESDATA;
// dll側の領域
static TYPESDATA stockdt[5];
static int stockidx=0;
// DLL側関数の例として以下のような2関数を用意していたとする
// データをDLL側に渡す関数(stock_pushd)
int WINAPI stock_pushd(TYPESDATA *psetdt)
{
if( 4<stockidx) return -1;
memcpy(&stockdt[stockidx++],
psetdt,sizeof(TYPESDATA));
return stockidx;
}
// DLL側からデータを受け取る関数(stock_popd)
int WINAPI stock_popd(TYPESDATA *psetdt)
{
if( 0==stockidx) return -1;
memcpy(psetdt,&stockdt[--stockidx],sizeof(TYPESDATA));
return stockidx+1;
}
--------------------------------------------------------------------------
C#側
--------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
namespace TestCSharp
{
// C#側プログラムで実際に使用するデータ用クラス
public class csData
{
public string message;
public int sw1;
public string Stock;
public int sw2;
public csData(){
message = string.Empty;
sw1=0;
Stock=string.Empty;
sw2=0;
}
}
// C#側で、DLLとやり取りを行うクラス
public class testdllApi
{
//----------------------------------------------------------
//構造体定義
//----------------------------------------------------------
// typedef struct typstrData
// {
// char strMsg[256];
// int sw;
// char strStok[128];
// int sw2;
// }TYPESDATA;
// この構造体と同じレイアウトにするには以下のような記述
[StructLayout(LayoutKind.Sequential)]
public struct dll_TYPESDATA
{
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = (int)256)]
public string strMsg;
public int sw;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = (int)128)]
public string strStok;
public int sw2;
}
//----------------------------------------------------------
// 関数定義
//----------------------------------------------------------
// DLL側の関数を使用できるように定義
[System.Runtime.InteropServices.DllImport("testdll.dll")]
public static extern System.Int32
stock_pushd(ref dll_TYPESDATA psetdt);
[System.Runtime.InteropServices.DllImport("testdll.dll")]
public static extern System.Int32
stock_popd(ref dll_TYPESDATA psetdt);
//----------------------------------------------------------
public testdllApi() { /* コンストラクタ */ }
// C#側ではこのメソッドを使用する(pushd)
public int pushd(csData pdt)
{
dll_TYPESDATA dt = new dll_TYPESDATA);
dt.strMsg = pdt.message;
dt.sw = pdt.sw1;
dt.sw2 = pdt.sw2;
dt.strStok = pdt.Stock;
int nans = stock_pushd(ref dt);
return nans;
}
// C#側ではこのメソッドを使用する(popd)
public int popd(ref csData pdt)
{
dll_TYPESDATA dt = new dll_TYPESDATA();
int nans = stock_popd(ref dt);
pdt.message = dt.strMsg ;
pdt.sw1 = dt.sw;
pdt.sw2 = dt.sw2;
pdt.Stock = dt.strStok;
return nans;
}
}
}
Posted by のんきよね at 20:10│Comments(0)
│.NET(開発)