Please be aware that the content in SAP SQL Anywhere Forum will be migrated to the SAP Community in June and this forum will be retired.

Hi,

I am trying to call some Win32API external functions in kernel32.dll from within SQL Anywhere 12.0.1 database server. Everything works well on 32-bit Windows (XP and 7), but nothing works on 64-bit Windows (7 and 8).

When I declare a function WITHOUT the LANGUAGE clause on 32-bit Windows, the function executes normally. When I do the same on 64-bit Windows I get the following error message:
"Version 'V0' interface used by external function call 'FunctionName' is not supported for execution in the current context."

When I declare a function WITH the LANGUAGE clause (C___ESQL32 or C_ESQL64) the error message disappears, the function seems to execute, but "does nothing". I can't get any return value or OUT arguments, everything is NULL. Executing functions in the external context (with the LANGUAGE clause) doesn't work at all, even on 32-bit Windows.

I have installed the latest EBF, tried with database engine and server, disabled antivirus and firewall - nothing helps. I have tried several Win32API functions: GetVersion, GetCurrentDirectoryA, GetVolumeInformationA, MessageBoxA, ... but here is the simplest example with a function that has no arguments:

create function SFGetVersion ( )  
returns integer  
external name 'GetVersion@kernel32.dll' language C_ESQL32 (or C_ESQL64 for 64-bit Win);

select SFGetVersion();

Where do I make mistake? Could anyone manage to get this function execute successfully in any context on 32-bit and 64-bit Windows? Is it possible at all to call Win32API functions from within SQL Anywhere server (I suppose it is - it works on 32-bit Win)?

Any help would be welcome. Thanks!

asked 20 Feb '13, 14:47

ZvonimirK's gravatar image

ZvonimirK
16113
accept rate: 0%


When calling an external function on Win64 you must use the "new" External Function API (new is relative since it has existed since v7). The "old" API is still allowed when using the 32bit server but its use is discouraged (it has not been updated since the new API was created).

In your particular case, the external DLL is missing the extfn_use_new_api() function and therefore the server thinks (correctly) that you are using the old API and it is not supported on 64bit platforms.

You can read more about writing external functions in the documentation. The install contains an example on how to use the new API as well.

permanent link

answered 20 Feb '13, 14:55

Mark%20Culp's gravatar image

Mark Culp
24.9k10141297
accept rate: 41%

edited 20 Feb '13, 14:57

Many thanks for your prompt reply! You probably spared me hours of useless experiments.

Just to be sure: definitely it is not possible anymore to directly call kernel32.dll, user32.dll and other Win32API functions on 64bit Windows platforms from within SQL Anywhere? Am I right?

And one more thing that still confuses me:
What do you exactly mean when you say "When CALLING an external function on Win64 you must use the "new" External Function API"? How "to use" the new API? When I CALL a function I don't use any API, except the one specified by the LANGUAGE clause. As I understand, the "new" API is used when you WRITE an external function. So, did you mean that I must write my own "intermediate" DLL, using "new" External Function API, and that functions from that DLL can in turn call eg. kernel32.dll functions?

Thank you once more!

(20 Feb '13, 15:51) ZvonimirK
Replies hidden

If you are using a 32bit server on a 64bit platform then you should still be able to call directly into DLLs provided the server can find the correct one! ... but if you are using a 64bit server then you cannot call directly into the system DLLs.

Re. "how to use the new API", please refer to the documentation links that I gave in my answer, and/or read Breck's blog postings which he has listed in his answer. If you have further questions about using the API then please post a new question.

(20 Feb '13, 16:45) Mark Culp
Comment Text Removed

Bright clear! Every day the things get more and more complicated, instead of simplified. What we could do earlier in one line of code, today we have to write a bunch to the "new" API.
Neverteless, warm regards!

(20 Feb '13, 19:14) ZvonimirK
Replies hidden

So you have used the "old API" to call external functions so far? (I'm somewhat surprised as the "new API" - as Mark has stated - has been introduced in ASA7, i.e. around the year 2000.)

IMHO, enhancing the existing API samples is not that difficult to do to call your required functions... - but of course you are right, it does require to write your own DLL, you can't simply call a WinAPI directly when using the "new API".

(21 Feb '13, 03:34) Volker Barth

Why are you all folks talking about using the "old" or the "new" API to CALL external functions? What's the difference between using the "new" and the "old" API in the above mentioned example? Is there any new syntax to CALL an external function?

The "new" API has to be used when you WRITE your own functions in your own DLL or am I wrong? But I don't write any functions, I just want to call an existing function in kernel32.dll. How am I supposed to do it whit the "new" API?

Even today (13 years after the year 2000) SQL Anywhere do the job on 32-bit systems as it always have done (I have been using it for 18 years). That's why I am surprised that everything changes when you are on 64-bit system. Even when I write the new "wrapper" DLL for Win32API functions, the way I CALL that functions doesn't change.

(21 Feb '13, 05:39) ZvonimirK
Replies hidden

Why are you all folks talking about using the "old" or the "new" API to CALL external functions? What's the difference between using the "new" and the "old" API in the above mentioned example? Is there any new syntax to CALL an external function?

No, the procedure call itself is the same, it's still "call MyFunc(...);".

Only the declaration will be different: As stated, to use the new external call API, you have to write your own DLL and can't call any standard DLL (as that won't have the extfn_use_new_api() function, apparently), so that DLL will be referred to in the function declaration.

Using the new API, you can then choose

  • to have the server load it in-process (by not using a LANGUAGE clause in the declaration - note: then the server's and the DLL's bitness must match, and it must be written in C/C++)
  • or use an external environment by specifying the according LANGUAGE clause like C_ESQL32 or JAVA, so you can choose the appropriate bitness and PL yourself.
(21 Feb '13, 06:01) Volker Barth

I am really not very happy to do the surplus job of writing a new DLL for an existing DLL and messing with the deploying of that DLL side by side with the SQL Anywhere setup. But the things are the way they are. Thank you for your patience and the effort to clear the things up.

(21 Feb '13, 06:14) ZvonimirK
1

I appreciate that there is some extra work for you to write a routine that interfaces between SA and the system function, but I would hope that writing such a routine would be very simple for you. The documentation and the SA installation as well as Breck's articles have many examples for you to get started.

Note that the new external function API provides many advantages over the former method:

  • the API is portable across all platforms and bitnesses
  • the API provides a method to cancel an external function call
  • the API provides a method to handle arbitrarily large BLOBs, and the content of the BLOBs do not need to be stored in contiguous memory nor even be resident in memory all at once (e.g. you could stream a blob to or from some external media device)
(21 Feb '13, 09:30) Mark Culp
showing 3 of 8 show all flat view
permanent link

answered 20 Feb '13, 16:18

Breck%20Carter's gravatar image

Breck Carter
32.5k5417261050
accept rate: 20%

Great links, thanks!

(20 Feb '13, 16:52) ZvonimirK
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×36
×23

question asked: 20 Feb '13, 14:47

question was seen: 3,925 times

last updated: 21 Feb '13, 09:31