delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2011/02/19/04:40:37

X-Recipient: archive-cygwin AT delorie DOT com
X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,SPF_HELO_PASS,TW_CP,TW_FW,TW_TF,T_RP_MATCHES_RCVD,T_TO_NO_BRKTS_FREEMAIL
X-Spam-Check-By: sourceware.org
To: cygwin AT cygwin DOT com
From: Jason Curl <jcurlnews AT arcor DOT de>
Subject: Re: I want to use DLL compiled with Cygwin with VC(VS2008).
Date: Sat, 19 Feb 2011 10:39:59 +0100
Lines: 224
Message-ID: <ijo35f$54i$1@dough.gmane.org>
References: <201102120245 DOT p1C2juUX029959 AT omx12 DOT ms DOT so-net DOT ne DOT jp> <20110212025813 DOT GA20293 AT ednor DOT casa DOT cgf DOT cx> <201102140403 DOT p1E43cc8002240 AT omx11 DOT ms DOT so-net DOT ne DOT jp>
Mime-Version: 1.0
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101207 Thunderbird/3.1.7
In-Reply-To: <201102140403.p1E43cc8002240@omx11.ms.so-net.ne.jp>
X-IsSubscribed: yes
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Unsubscribe: <mailto:cygwin-unsubscribe-archive-cygwin=delorie DOT com AT cygwin DOT com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

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 AT 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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019