From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17593 invoked by alias); 19 Feb 2011 09:40:29 -0000 Received: (qmail 17583 invoked by uid 22791); 19 Feb 2011 09:40:28 -0000 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 Received: from lo.gmane.org (HELO lo.gmane.org) (80.91.229.12) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 19 Feb 2011 09:40:21 +0000 Received: from list by lo.gmane.org with local (Exim 4.69) (envelope-from ) id 1PqjIT-0002O1-FI for cygwin@cygwin.com; Sat, 19 Feb 2011 10:40:13 +0100 Received: from dslb-084-056-030-155.pools.arcor-ip.net ([84.56.30.155]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 19 Feb 2011 10:40:13 +0100 Received: from jcurlnews by dslb-084-056-030-155.pools.arcor-ip.net with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 19 Feb 2011 10:40:13 +0100 To: cygwin@cygwin.com From: Jason Curl Subject: Re: I want to use DLL compiled with Cygwin with VC(VS2008). Date: Sat, 19 Feb 2011 09:40:00 -0000 Message-ID: References: <201102120245.p1C2juUX029959@omx12.ms.so-net.ne.jp> <20110212025813.GA20293@ednor.casa.cgf.cx> <201102140403.p1E43cc8002240@omx11.ms.so-net.ne.jp> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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@cygwin.com; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner@cygwin.com Mail-Followup-To: cygwin@cygwin.com X-SW-Source: 2011-02/txt/msg00446.txt.bz2 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 #include #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