みなさん、久しぶりの更新です。


今日はWIN32のDLLを.NETから呼び出すのを紹介します。


先にDLLのソースの元はだどさんのHPのサンプル を元にしました。


それと、参考になりそうなHPに宇宙仮面さんのところ があります。


では、さっそく。


まず、DLLのソースは次のように。


[username.cpp]

-----------------------------------------------

#include <windows.h>
#include <lmcons.h>
#include <tchar.h>
#include <stdio.h>
#include <string.h>

BOOL __stdcall PrintUserName(LPTSTR lpUserName,unsigned int szLen)
{
TCHAR szUserName[UNLEN + 1];
DWORD dwUNLen = UNLEN;

if(!GetUserName((LPSTR) szUserName,&dwUNLen)){
printf("Error: %u",GetLastError());
return FALSE;
}

_tprintf(TEXT("%s\n"),szUserName);

if(szLen < _tcslen(szUserName)){
return FALSE;
}

sprintf_s(lpUserName,sizeof(lpUserName),"%s",szUserName);

return TRUE;
}
-------------------------------------------------

[makefile]

------------------------------------------------------------------
TARGETNAME=username
DEFFILE=username
OUTDIR=.\chk
LINK32=link.exe

ALL : $(OUTDIR)\$(TARGETNAME).dll

CLEAN: -@erase /Q $(OUTDIR)\*

$(OUTDIR) :
if not exist $(OUTDIR)/$(NULL) mkdir $(OUTDIR)

CPP_PROJ=\
/MT\
/W4\
/Fo"$(OUTDIR)\\"\
/Fd"$(OUTDIR)\\"\
/c\

LINK32_FLAGS=\
advapi32.lib\
/subsystem:windows\
/pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\
/out:"$(OUTDIR)\$(TARGETNAME).dll"\
/DEBUG\
/RELEASE\
/DLL\
/DEF:$(DEFFILE).def

LINK32_OBJS=\
$(OUTDIR)\$(TARGETNAME).obj

$(OUTDIR)\$(TARGETNAME).dll : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)

.cpp{$(OUTDIR)}.obj:
$(CPP) $(CPP_PROJ) $<


中身の主な内容はだどさんのHP を参照してください。


では、今度は呼び出す側の方のソースを紹介します。


[form1.cs]


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace SampleProject{
public partial class Form1 : Form
{
[DllImport("username.dll")]
extern static bool PrintUserName(StringBuilder str,UInt32 ui);

public Form1()
{
InitializeComponent();
}

private void btnCallDLL_Click(object sender, EventArgs e)
{
btnCallDLL.Enabled = false;
lblUserName.Text = "";
UInt32 uiSize = 256;

StringBuilder strBldr = new StringBuilder((int)uiSize);

bool bRet = PrintUserName(strBldr, uiSize);

if (!bRet)
{
MessageBox.Show("PrintUserNameでエラーです");
}

lblUserName.Text = strBldr.ToString();
btnCallDLL.Enabled = true;
}
}
}

-----------------------------------------------------------


こんな感じでしょうか。


注意する点は、文字列型の受け渡しに、.NET側はStringではなく、StringBuilderを使うという点です。


また、読み込んでおくべき名前空間にSystem.Runtime.InteropServicesが必要だということです。


それと、実行時に注意する点は、username.dllを.NETの実行ファイルと同じフォルダにしておいてください。


今回はDLL側のエクスポートしている関数が一つでしたので特に設定は多くはなかったのですが、複数の関数をエクスポートしているときはどうなるのでしょうか。


私もあとで調べてご報告したいと思います。


では(=⌒▽⌒=)