This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: I want to use DLL compiled with Cygwin with VC(VS2008).


On 14/02/2011 05:03, Y.Hosoi wrote:
Thank you.

However, it did not move well.

If test.dll is done in LoadLibrary, Access Violation is generated.

Are you still amused something?


[main source code]


#include "stdafx.h"
#include "windows.h"

#ifdef __cplusplus
extern "C"{
#endif

typedef int (*TFUNC)(void);

typedef void (*Tinit)(void);

int _tmain(int argc, _TCHAR* argv[])
{
	int i;

	HINSTANCE	h;
     	HINSTANCE	hInstDLL;

	Tinit		init;
	TFUNC		DllFunction;
	DWORD		ErrNo;

	h = LoadLibrary( TEXT( "cygwin1.dll" ) );
	init = (Tinit)GetProcAddress( h, "cygwin_dll_init" );

init();

	hInstDLL = LoadLibrary( TEXT( "test.dll" ) );		/* !Access Violation! */
	if( hInstDLL == NULL )
	{
		ErrNo = GetLastError();
		return 0;
	}
	DllFunction = (TFUNC)GetProcAddress( hInstDLL, "hello" );
	i = DllFunction();

	FreeLibrary( hInstDLL );
	FreeLibrary( h );

	return 0;
}

#ifdef __cplusplus
}
#endif


Try the following code. This was pulled from the Cygwin sources. There is a test case that does exactly this, loads cygwin1.dll dynamically. You need to make sure you allocate stack. This was compiled with MINGW. This is part of a larger program, so it might need some adjustments. The function cygloadCRTStartup() is pretty much from the sources.


Note that the entry point needs to be set with the linker option:
-Wl,-entry -Wl,_cygloadCRTStartup@0

#include <windows.h>
#include <stdio.h>
#include "getopt.h"

#define CYGHELP_SUCCESS           EXIT_SUCCESS
#define CYGHELP_ARG_ERROR         1
#define CYGHELP_DLL_NOT_FOUND     100
#define CYGHELP_DLL_NOT_SUPPORTED 101
#define CYGHELP_INTERNAL_ERROR    255

typedef void    (__cdecl cdi_t)(void);
typedef void    (__cdecl cctfwp_t)(const char *path, char *win32path);
typedef void    (__cdecl cctfpp_t)(const char *path, char *posixpath);

int mainCRTStartup ();

int __stdcall cygloadCRTStartup ()
{
	char   padding[32768];
	size_t delta;
	int    result;
	char   block[32768];
	char  *stackbase;
	char  *_stackbase;
	char  *_end;

	_end = padding + sizeof(padding);
#ifdef __GNUC__
	__asm__ (
		"movl %%fs:4, %0"
		:"=r"(stackbase)
    );
#else
	__asm {
		mov eax, fs:[4];
		mov stackbase, eax;
	}
#endif
	_stackbase = stackbase;

	// We've gotten as close as we can to the top of the stack.  Even
	// subverting the entry point, though, still doesn't get us there-- I'm
	// getting 64 bytes in use before the entry point.  So we back up the data
	// there and restore it when the destructor is called:
	if ((_stackbase - _end) != 0) {
		delta = (_stackbase - _end);
		memcpy (block, _end, delta);
    }
	result = mainCRTStartup ();
	memcpy(_end, block, delta);
	return result;
}

int main(int argc, char **argv)
{
HMODULE cygwinDll;
DWORD winres;
cdi_t *cygwin_dll_init;
cctfwp_t *cygwin_conv_to_full_win32_path;
cctfpp_t *cygwin_conv_to_full_posix_path;
const char *dll = "cygwin1.dll";
const char *ppath = NULL;
const char *wpath = NULL;

char module[MAX_PATH];
char buff[MAX_PATH];
int i;
int c;

// Get any options the user provides
opterr = 0;
while ((c = getopt(argc, argv, "c:p:w:")) != -1) {
switch (c) {
case 'c':
dll = optarg;
break;
case 'p':
ppath = optarg;
break;
case 'w':
wpath = optarg;
break;
case '?':
if (optopt == 'c') {
fprintf(stderr, "Option -%c requires the full name for the Cygwin DLL\n", optopt);
} else if (optopt == 'p') {
fprintf(stderr, "Option -%c requires the Posix path to convert\n", optopt);
} else if (optopt == 'w') {
fprintf(stderr, "Option -%c requires the Windows path to convert\n", optopt);
} else {
fprintf(stderr, "Unknown option -%c\n", optopt);
}
return CYGHELP_ARG_ERROR;
default:
fprintf(stderr, "Argument %c given, unknown handler\n", c);
return CYGHELP_INTERNAL_ERROR;
}
}


	// Load the library and determine the full path to the library (as
	// determined by windows)
	cygwinDll = LoadLibrary(dll);
	if (!cygwinDll) {
		fprintf(stderr, "Couldn't find %s\n", dll);
		return CYGHELP_DLL_NOT_FOUND;
	}
	winres = GetModuleFileName(cygwinDll, module, MAX_PATH);
	if (!winres) {
		winres = GetLastError();
		fprintf(stderr, "GetModuleFilename returned error %d\n", winres);
		return CYGHELP_DLL_NOT_SUPPORTED;
	}
	
	cygwin_dll_init = (cdi_t *)
		GetProcAddress(cygwinDll, "cygwin_dll_init");
	if (!cygwin_dll_init) {
		fprintf(stderr, "Couldn't find cygwin_dll_init\n");
		return CYGHELP_DLL_NOT_SUPPORTED;
	}
	
	cygwin_conv_to_full_win32_path = (cctfwp_t *)
		GetProcAddress(cygwinDll, "cygwin_conv_to_full_win32_path");
	if (!cygwin_conv_to_full_win32_path) {
		fprintf(stderr, "Couldn't find cygwin_conv_to_full_win32_path\n");
		return CYGHELP_DLL_NOT_SUPPORTED;
	}
	
	cygwin_conv_to_full_posix_path = (cctfpp_t *)
		GetProcAddress(cygwinDll, "cygwin_conv_to_full_posix_path");
	if (!cygwin_conv_to_full_posix_path) {
		fprintf(stderr, "Couldn't find cygwin_conv_to_full_posix_path\n");
		return CYGHELP_DLL_NOT_SUPPORTED;
	}
	
	// Initialise the library. The first line is always the name of the
	// module. Then we print the result that the user expects. This allows
	// programs to know what library is in use and to easily parse the output
	// for their needs
	cygwin_dll_init();
	printf("%s\n", module);
	if (ppath) {
		cygwin_conv_to_full_win32_path(ppath, buff);
		printf("%s\n", buff);
	}
	if (wpath) {
		cygwin_conv_to_full_posix_path(wpath, buff);
		printf("%s\n", buff);
	}
	
	// We've finished now, so let's exit
	FreeLibrary(cygwinDll);
	return CYGHELP_SUCCESS;
}


-- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]