
#include <Windows.h>

#include <cstdio>
#include <memory>    	// for unique_ptr.
#include <type_traits>	// for remove_pointer.

int main()
{
	auto hm1 = ::LoadLibraryW(LR"unko(C:\Projects\TestDll\Debug\TestDll.dll)unko");
	if ( hm1 == nullptr )
	{
		std::printf("load1 failed\n");
		return ~0;
	}
	std::unique_ptr<std::remove_pointer<decltype(hm1)>::type, void (*)(decltype(hm1))>
		disposer1(hm1, [](decltype(hm1) h){ ::FreeLibrary(h); });
	std::printf("dll1 okay\n");

	auto hm2 = ::LoadLibraryW(LR"unko(C:\Projects\TestDll\TestDll.dll)unko");
	if ( hm2 == nullptr )
	{
		std::printf("load2 failed\n");
		return ~0;
	}

	std::unique_ptr<std::remove_pointer<decltype(hm2)>::type, void (*)(decltype(hm2))>
		disposer2(hm2, [](decltype(hm2) h){ ::FreeLibrary(h); });
	std::printf("dll2 okay\n");
	
	auto *pf1 = reinterpret_cast<long long (__stdcall *)()>(::GetProcAddress(hm1, "f"));
	if ( pf1 == nullptr )
	{
		std::printf("getprocaddress1 failed\n");
		return ~0;
	}
	
	auto *pf2 = reinterpret_cast<long long (__stdcall *)()>(::GetProcAddress(hm2, "f"));
	if ( pf2 == nullptr )
	{
		std::printf("getprocaddress2 failed\n");
		return ~0;
	}

	std::printf("%lld\n", pf1()); // 1
	std::printf("%lld\n", pf1()); // 2
	std::printf("%lld\n", pf1()); // 3

	std::printf("%lld\n", pf2());; // 1
	std::printf("%lld\n", pf2());; // 2
	std::printf("%lld\n", pf2());; // 3
}

/*
 TestDll.dll

#include <Windows.h>

namespace unko
{
	long long g_count;
}

LONGLONG __stdcall f()
{
	return ++unko::g_count;
}


*/
