Okay, you C types: This seems pretty straight forward to translate:

Okay, you C types:  This seems pretty straight forward to translate:

short GeoEngCheckDbAvailability(char *pSearchPath,
char *pDbName,
char *pUserDictionaryPath,
short *pDbFlags);

But the translation I have is:

function GeoEngCheckDbAvailability(pSearchPath: PAnsiChar; pDbName: PAnsiChar; pUserDictPath: PAnsiChar; pDbFlags: pshort): short;

seems to be causing problems, specifically AV's.

Help?

Comments

  1. I'm not really a c type, but what about your calling convention?  Don't you need to append ;cdecl, or are you just not showing that in your code snippet?

    ReplyDelete
  2. Oh, sorry -- the declaration is stdcall;

    ReplyDelete
  3. TGeoEngCheckDbAvailability    = function(pSearchPath: pAnsichar; pDbName: PAnsiChar; pUserDictPath: PAnsiChar; pDbFlags: pshort): short; stdcall;

    ReplyDelete
  4. I wouldn't know.  I'm a normal person and don't understand cruddy languages to translate.    ;-)

    ReplyDelete
  5. I should add that this works fine in our D7 code base and I'm now having troubles in XE3.  I changed the PChars all to be PAnsiChars in the XE3 version.

    ReplyDelete
  6. Dumb question: Have you looked in Windows.pas for similar?

    ReplyDelete
  7. Good idea --

    I searched, and can't seem to find a similar construct.

    ReplyDelete
  8. Nick Hodges It's been a while, and I haven't had to mess with that stuff since D7, in fact, but in XE's Windows.pas, I see this:
    LPCTSTR = {$IFDEF UNICODE}PWideChar{$ELSE}PAnsiChar{$ENDIF};
     So, just for fun, what if you do this:

    function GeoEngCheckDbAvailability(pSearchPath: LPCTSTR; pDbName: LPCTSTR; pUserDictPath: LPCTSTR; pDbFlags: pshort): short;

    If it makes a difference, then I would anticipate that PWideChar is being applied....

    ReplyDelete
  9. Nick Hodges It is likely that the implementation is in a DLL. If the DLL is using AnsiChar, then the translation you have is correct (Add calling convention). You cannot pass PChar (unicode) if the DLL expect ASCII characters.
    You may want ot build a wrapper to translate between ASCII (ansi) and unicode which will be easier to use in the application.

    ReplyDelete
  10. The weird thing is that it throws the AV's, but then it works.

    ReplyDelete
  11. Probably a calling convention issue. Do you have the original C source code (The .H file) ?

    ReplyDelete
  12. That's the thing -- it works fine with stdcall in Delphi 7.

    The plot thickens:  If I run the EXE outside of the debugger, I see no AVs.

    ReplyDelete
  13. I am trying to track down the original *.h file....

    ReplyDelete
  14. TDump is your friend. Run TDump against the DLL with -ea parameter. Save to a convenient text file, then go spelunking.

    ReplyDelete
  15. When I did have to this stuff, TDump was a lifesaver. I also found it essential to have a unit which provided the conversion of all DLL funcs to Delphi versions, and did so in a way that gave me useful debug info. For one thing, you are then working against the exported calls, not what a doc claims they are....

    ReplyDelete
  16. i once had an issue with a DLL. It seems to work, but not always... The problem was that the DLL was using cdecl calling convention. try it!

    ReplyDelete
  17. I can't seem to get TDump to tell me anything about parameters on the exports.....

    ReplyDelete
  18. I can try to dig out some old dump files. As I recall, though, TDump will give you a byte count for the parameters. As the call you specified is passing 5 pointers, then there should be 20 bytes of parameters. As Francois said, though, the calling convention can be an issue. Try changing to cdecl, which is the common C convention, and see whether the AVs go away. I can't offer a reason why it would be fine on D7, and not on XE3, however.

    ReplyDelete
  19. Nick Hodges I have located an old (TDump) export in which there are multiple sets of exported function specs. This is from a DLL which originally exported C++ classes (don't ask), then added plain C style funcs and also numerically indexed functions. In the C style functions, I see at the end of the name an @ followed by a number:  MyFunc@20, for example. I'm sorry, but I do not know whether this is a common format, as I worked long term with only a few DLLs.

    ReplyDelete
  20. Run this in D7 in debugger, check the ASM code to see how parameters are pushed; repeat the drill in XE3.

    ReplyDelete
  21. Just a hint: try to debug both cases in D7 & XE3 with OllyDBG to figure out the difference.

    ReplyDelete
  22. BTW, changing to cdecl locked everything up really badly.....

    ReplyDelete
  23. Nick Hodges Then that's not the issue. ;)  But at least now you know! I didn't ask before, but you are building for 32-bit, right?

    ReplyDelete
  24. OK, it only occurred to me a short time ago that on XE3 there was the potential for complexities well beyond any experience I can claim.

    ReplyDelete
  25. Primož Gabrijelčič My CPU Window skills are fairly limited, so here's the picture from D7 --

    Well, you can't put a picture in a comment, so I'll try it in a new message....

    ReplyDelete
  26. To put a picture in a comment - upload to G+ and paste link.

    ReplyDelete
  27. Could some of the parameters be var v:type instead of v:ptype ?

    ReplyDelete
  28. Nick Hodges re: screenshots in comments.  That's why I really like the screen shot annotation utility called Clarify (mac and windows versions).

    Check out the shot I made of this conversation, with some annotations, including highlighting, blurring, arrows, text, etc.  Took about 1 minute. 

    http://trident.clarify-it.com/d/mgg436
    (Click image to zoom)

    It's easy to use, but best of all you get free webspace to post your shots to a customizable page, directly from the Clarify application.  You can also export to HTML, PDF to file or email, and EverNote.

    Very handy for both giving and receiving support, especially in situations where you can't post a screen shot directly.  e.g. web form support mail, G+ comments, etc.

    http://www.clarify-it.com/

    ReplyDelete
  29. Trace the declaration of pshort. I might not be what you think.

    ReplyDelete
  30. ^ Yes I was going to suggest using Integer (or Smallint) instead if Short in your Delphi declaration.

    ReplyDelete
  31. short is declared as:

    type
      short          = word;
      pshort         = ^short;

    ReplyDelete
  32. So am I off base saying the C would actually have to be:

    unsigned short GeoEngCheckDbAvailability(char *pSearchPath,
    char *pDbName,
    char *pUserDictionaryPath,
    unsigned short *pDbFlags);

    I don't suppose that is all that important but it's more correct. Maybe your short should be type Smallint not Word.

    ReplyDelete
  33. I found the API you are using. Downloaded the sample programs and compiled using MSVC. here is the result for the generated code:
    ; 143  :     /*
    ; 144  :      * Check availability, we only initialize if STREET_DB and CENTROID_DB
    ; 145  :      *    ara available.
    ; 146  :      */
    ; 147  :     retCode = GeoEngCheckDbAvailability (dbPath, dbName, NULL, &dbFlags);
      002fa 8d 85 c8 fe ff
     ff   lea  eax, DWORD PTR _dbFlags$[ebp]
      00300 50   push  eax
      00301 6a 00   push  0
      00303 8b 8d f8 fe ff
     ff   mov  ecx, DWORD PTR _dbName$[ebp]
      00309 51   push  ecx
      0030a 8d 95 fc fe ff
     ff   lea  edx, DWORD PTR _dbPath$[ebp]
      00310 52   push  edx
      00311 ff 15 00 00 00
     00   call  DWORD PTR __imp__GeoEngCheckDbAvailability@16
      00317 66 89 85 cc fe
     ff ff   mov  WORD PTR _retCode$[ebp], ax
    ; 148  :  if (retCode != SUCCESS)


    In the sample program, I see dbPath is déclared as an array of 256 chars. Maybe this is important. dbName is just a char* so no storage except the exact character number. dbFlags is a short.
    sizeof(short) is 2, so it is a 16 bit integer.

    ReplyDelete
  34. François Piette Well, that was above and  beyond.  ;-)

    I'll try playing around with dbPath as and array of ansichar.

    ReplyDelete
  35. Nick Hodges Also, I have found  in the past that some of these DLL calls will fail unless I FillChar the entire byte array with 0 before calling.

    ReplyDelete
  36. Bill -- Good idea, but that didn't help either.  ;-)

    ReplyDelete
  37. Nick Hodges Man, you just won't make it easy, will you? ;)  Which compiler are you on?

    ReplyDelete
  38. Iman Crawford I changed the declaration of short to be a smallint.  Didn't help.  ;-)

    ReplyDelete
  39. Nick Hodges Oh well. Don't have it, else I would volunteer to fight with it myself. I can't believe that none of the suggestions have gotten you to a solution. Whose DLL is this?

    ReplyDelete
  40. try 32 bit integer.  I noticed there is a mm16*.dll and mm32*.dll.  Maybe the documentation is wrong.

    ReplyDelete
  41. Iman --

    Thanks for helping out --

    I only have the mm32v12.dll on my hard drive.

    ReplyDelete
  42. Iman --  Great sample code, by the way.  

    From another sample at that sight, the right parameter is declared as:

    char *search_path, char *db_name

    which is exactly what I'm doing.  

    Very, very weird.

    ReplyDelete
  43. How do you load the function?
    Implicit via index or name, or explicit?
    I guess you already checked if you had the right index?

    ReplyDelete
  44. BTW, Isn't there an OLE Automaton version of this as well?
    Could it be expecting OLE types?

    ReplyDelete
  45. It's all dynamic, using LoadLibrary and GetProcAddess.

    The weird thing is that it all works despite the AV.

    ReplyDelete
  46. That is weird - perhaps the AV is "data driven" ?

    ReplyDelete
  47. Nick Hodges Huh? What if you pass in the third param as a zero-filled array, instead of the nil?

    ReplyDelete
  48. You could reduce the D7 project to its simplest compilable project, upload it somewhere and let us figure it out... ;o) provided the DLL that house the GeoEngCheckDbAvailability is not some commercial product...

    ReplyDelete

Post a Comment