on 2012 Mar 28 9:38 AM
Has someone successfully created a 64 bit DLL for external procedures?
I had a few serious issues with external environments (instability, slow) and therefore wanted to go back the "old" way of not using it. I don't mean the old interface for external librarys i use extfn_use_new_api. I successfully created a few dll's with Delphi 2006 but as we gradually moved to 64 bit servers (Delphi 2006 is 32 bits only and you can't use 32 bit dll's with a 64 bit server without an external environment) i also wanted to create 64 bit dll's. As i had Visual Studio 2010 lying around i tried my luck and created a very simple test dll compiled for the x64 platform:
#include "stdafx.h" #include "extfnapi.h" extern "C" __declspec(dllexport) unsigned int extfn_use_new_api( void ) { return( EXTFN_API_VERSION ); } extern "C" __declspec(dllexport) void lib64test( an_extfn_api *api, void *arg_handle ) { } ALTER PROCEDURE "FCT"."Test64"() external name 'lib64test@Test64.dll'
But when i dont use an external environment i get the error message:
Could not load dynamic library 'Test64.dll' (-620)
with external environment (language c_odbc64):
Procedure 'Test64' terminated with unhandled exception 'Test64.dll could not be found' (-91)
I can load 32 bit dll's from the directory, i even copied the dll into the appropriate bin64 directory to no avail.
Request clarification before answering.
I started the db with dbeng and got the error message that "msvcr100.dll" would be missing. This error message doesn't get shown if you use a service as it can't "communicate" with the desktop. As always the problem sits behind the keyboard. Sorry for all the noise and thanks for the incredibly fast help. Just statically linking the runtime library with /MT and all is good. How should i close this thing now?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
...and it's always helpful to get to know what - sometimes unexpected - solution was found.
Besides that: I do learn (or better: get reminded) from your experience that one should try with dbeng12/dbsrv12 as a "normal application" instead of as a service when something doesn't work as expected - simply as services sometimes are less verbose in their error messages/warnings...
Quite often the "could not load" message simply means the dll isn't there (or isn't in the right place, same thing from the server's point of view).
I assume you picked the right platform and other properties when building...
Does your procedure really have no parameters? I've never used ALTER PROCEDURE, only DROP and CREATE, and they all have parameter lists.
I'm fairly certain some (a lot?) of the following #stuff is unnecessary, but that's what happens with legacy code.
Anyway, the following code works with the 64-bit SQL Anywhere 12.0.1 server, and the CREATE PROCEDURE dynamically chooses which DLL to used based on which bit-ness of SQL Anywhere is in use.
#if defined( WIN32 ) #include <windows.h> #endif #include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #if defined( _MSC_VER ) #include <tchar.h> #endif #include "extfnapi.h" #include "Shlobj.h" #if !defined( _unused ) #define _unused( i ) ( (i) = (i) ) #endif #if !defined( TRUE ) #define TRUE 1 #endif #if !defined( FALSE ) #define FALSE 0 #endif #if defined( WIN32 ) #define _UINT32_ENTRY unsigned int FAR __stdcall #define _VOID_ENTRY void FAR __stdcall #else #define _UINT32_ENTRY unsigned int #define _VOID_ENTRY void #endif #define int64 __int64 #define uint64 unsigned __int64 #if defined( WIN32 ) int __stdcall LibMain( HANDLE inst, ULONG reasoncalled, LPVOID reserved ) /*********************/ { _unused( inst ); _unused( reasoncalled ); _unused( reserved ); return( 1 ); } #endif __declspec(dllexport) _UINT32_ENTRY extfn_use_new_api( void ) { return( EXTFN_API_VERSION ); } __declspec(dllexport) _VOID_ENTRY get_first_dsn ( an_extfn_api *api, void *arg_handle ) { ...etcetera SET @sql = STRING ( 'CREATE PROCEDURE rroad_get_first_dsn ( ', 'IN dsn_type_code UNSIGNED INTEGER, ', IF @rroad1_dll_name = 'rroad1.dll' THEN 'OUT odbc_hkey UNSIGNED INTEGER, ' ELSE 'OUT odbc_hkey UNSIGNED BIGINT, ' ENDIF, 'OUT dsn_index UNSIGNED INTEGER, ', 'OUT odbc_dsn VARCHAR ( 255 ), ', 'OUT odbc_driver VARCHAR ( 255 ), ', 'OUT return_code UNSIGNED INTEGER, ', 'OUT diagnostic_code UNSIGNED INTEGER, ', 'OUT diagnostic_string VARCHAR ( 255 ) ) ', 'EXTERNAL NAME ''get_first_dsn@', @foxhound_db_folder, '\\\\', @rroad1_dll_name, '''' ); EXECUTE IMMEDIATE @sql;
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Martin... yeah, speed-reading-without-comprehending leaves something to be desired 🙂
This is just a test as simple as i could imagine, because the real function also did'nt work. I want to use zlib compression in our application to compress big documents (up to 5 Mb very compressible rtf text) before saving them in the db. I could use the compress flag of the column i know, but then the problem becomes the network and client memory usage. I just want to be able to decompress the content in the database on ocassion, not only in the client. I can load the same code compiled as 32 bit but not as x64. I also checked your screenshot with my settings and couldn't find a difference. Perhaps i have to use the defines from the example code, but i'm not a big fan of them, makes code very fast really unreadable. But i'm a Delphi porgrammer so that could be the real problem.
FWIW, if you want to compress data on demand, there are also the builtin COMPRESS()/DECOMPRESS() functions. - Note, they are executed in the server, not on the client, so they won't help to reduce network traffic or the like.
We have customers with version 8 to 12 and i want to reliably decompress in our client application. But that was a good tip nevertheless, i thougt compress/decompress would use a proprietary format, but it seems it would be possible to decompress in a client application, though i didnt't test this.
User | Count |
---|---|
68 | |
16 | |
12 | |
7 | |
7 | |
4 | |
4 | |
4 | |
4 | |
3 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.