_CONSOLE
매크로는 하위시스템이 콘솔일때 정의된다.
_WINDLL
매크로는 dll프로젝트일때 정의된다.
http://stackoverflow.com/questions/7697859/visual-studio-macro-for-checking-configuration-type-exe-dll
이를 이용하면 dll 프로젝트에서 테스트를 위해 main 함수와 함께 사용할 수 있다.
#ifdef _WINDLL
#include<Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#else
#include<iostream>
int main(){
std::cout << "i'm test function" << std::endl;
}
#endif
######a. DLL프로젝트를 빈 프로젝트로 생성한다.
######b. 만들고자 하는 함수를 아래와 같은 형식으로 정의 한다.
extern "C"{
__declspec(dllexport) int foo(int a){
return a;
}
}
C/C++
(암시적)프로젝트 설정의 추가 라이브러리 디렉터리 에서 lib 파일을 추가해준다.
또는, #pragma comment
키워드로 추가할수 있다.이거 좀 비추
사용하는 곳에서는 함수 정의만 있으면 된다. 헤더파일을 만들어 두는게 더 좋은 방식이다.
dll은 exe와 같은 경로에 있어야 한다.
또는 32비트 dll의 경우 C:\Windows\SysWOW64
에 있거나, 64비트 dll의 경우 C:\Windows\System32
에 있으면 된다.
C/C++
(명시적)말은 필요없다. 코드로 설명한다.
뭔소린지 모르겠다면, 함수 포인터 부분을 공부하고 오자.
int(*foo)(int a)= NULL;
HMODULE hMod=LoadLibraryA("a.dll");
if(hMod==NULL){
fprintf(stderr,"Dll load fail(%d)\n",GetLastError());
}
foo=(int(*)())GetProcAddress(hMod,"foo");
//foo();
FreeLibrary(hMod);
이때 dll 로드가 실패한다면 GetLastError
함수를 통해 실패한 이유를 알 수 있다.
193 번 에러는 해당 dll과 client 프로그램의 비트수가 맞지 않아 생기는 에러이다.
(e.g. 64비트 프로세스에서 32비트 dll을 호출)
C#
(암시적)using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace cs_program
{
class Program
{
//외부 함수 Import
[DllImport("a.dll")]
public static extern int foo(int a);
static void Main(string[] args)
{
foo(5); //그냥 호출 하면 됨.
}
}
}
C#
(명시적)using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace cs_program
{
class Program
{
//dll을 로드하기 위한 함수 import
[DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
[DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
[DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
static extern bool FreeLibrary(int hModule);
[DllImport("kernel32.dll", EntryPoint = "GetLastError")]
static extern int GetLastError();
//함수를 받기위한 원형 선언
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int FUNC_foo(int);
FUNC_foo foo;
static void Main(string[] args)
{
IntPtr dll = LoadLibrary("a.dll");
if (dll == IntPtr.Zero)
{
MessageBox.Show(GetLastError().ToString());
Environment.Exit(1);
}else
{
IntPtr func_addr= GetProcAddress(dll, "foo");
foo = (FUNC_foo)Marshal.GetDelegateForFunctionPointer(func_addr, typeof(FUNC_foo));
}
foo(5);
}
}
}
####References