none
Dll Problem with C# and InterBase RRS feed

  • Question

  • I don't know if this is the right plasce to ask, but here's the problem. I had written a C# dll. I need to call only one method from it(the method is public and returns int). I created an interface in which i declared the method. I know i can't call a c# method directly from interBase, so i created a delphi dll, which calls the c# dll. So, this delphii dll is working perfect in a delphi *.exe, but when i try to use it under interbase using:


    Code Snippet

    declare external function send

    integer, integer, integer, string, integer, integer, integer

    returns integer by valueentry_point "test" module_name "a.dll"



    and then execute the following:

    Code Snippet

    select send(1,2,3,'df',4,5,1) 

    from dump


    it returns -2147418113
    if anyone can help, please do. if this isn't the right place to ask, please tell me where to ask and if you need some of the code, tell me, i'll post it here
    thhanks in advance
    Wednesday, March 12, 2008 8:09 AM

Answers

  • CoInitialize and CoInitializeEx are part of the Windows API. You must call one of them before doing anything with COM. In some cases, though, Delphi will do this for you. It's pretty easy to figure out when you do and don't need to call it. If you need to call it and you forget to do so, you'll get a runtime error that "CoInitialize has not been called." If you don't need to call it (because Delphi has done it for you, based on what is in your project), you'll get an error to that effect, too.
    Wednesday, March 12, 2008 2:56 PM
  • Yes, you must set IsMultiThread (not IsMultiThreading) true. I do it in the initialization section of the unit, as shown in the article. However, I doubt this has anything to do with the problems you describe above.
    Friday, March 14, 2008 2:57 PM

All replies

  • Is that an Interbase error code it returns (it does look like one)? If so, check the Interbase book for it (you do have it? It's an excellent resource) or look for it online.

     

    Most likely IB is complaining about your .NET assembly not being a proper DLL. IB is not a .NET application, it's a Win32 application and may not like .NET assemblies.
    Wednesday, March 12, 2008 12:29 PM
  • i'm looking online for 3 days. it's not an error code, it's the value it returns Sad
    Wednesday, March 12, 2008 1:02 PM
  • Your UDF declaration is certainly wrong, as "string" isn't a supported UDF argument type. You would use CSTRING(n) instead. But the result suggests that you may have by value / by ref incorrect somewhere, too. Hard to tell without seeing the Delphi source. Debugging the Delphi DLL (with IB as the host application) should help sort that out.

    The best place to post such questions is to point your newsreader at news://newsgroups.borland.com/borland.public.interbase.general.

    -Craig
    Wednesday, March 12, 2008 2:04 PM
  • i tried using CSTRING and VARCHAR. Here's the delphi code for the dll:

    Code Snippet

    uses
      ShareMem,
      SysUtils,
      Classes,
      ComObj,
      SoapHttpMessaging_TLB in 'C:\Program Files\Borland\Delphi7\Imports\SoapHttpMessaging_TLB.pas';

    {$R *.res}
    function test(var a,b,c: Integer; var d: PChar; var e,f,g:Integer): integer; safecall; export;
    var
      v: ISendDeviceEvent;
    begin
      v := CreateComObject(CLASS_SoapHttpMessaging_) as ISendDeviceEvent;
      Result := v.SendDeviceEvent(a,b,c,d,e,f,g);
    end;

    exports test;

    i found out that whenever i use the safecall directive the result is always -2147......... When i use any other directive like cdecl, stdcall, pascal or register it gives me the following error:

    Code Snippet

    General SQL error.
    A fatal exception occurred during the execution of a user defined function.
    An exception occurred that does not have adescription.  Exception number EEDFADE.


    SendDeviceEvent is the method i need to call from interBase. I have copied the C# dll in interBase\lib

    Wednesday, March 12, 2008 2:14 PM
  • There are a number of issues here.

    First, CSTRING is the only correct way to pass a string argument to a UDF. There is no other way to do it.

    Second, the calling convention of your Delphi export should be cdecl. The documentation says stdcall, but it's wrong. The code examples supplied with InterBase use the C calling convention, and that's what you should use, too.

    Third, you're getting an unhandled error inside your COM call. When you declare your Delphi function as safecall, Delphi wraps up the COM calls, handles the exception, and returns the HResult. Which in your case is -2147418113 = 0x8000FFF = E_UNEXPECTED = Catastrophic Failure = unhandled exception inside a COM call.

    This may be partially due to using the wrong calling convention in the first place, but since you say that it also happens when using cdecl you may need to look carefully at what you're passing the routine. Again, debug through the Delphi code.

    Fourth, I don't see a call to CoInitialize anywhere. Maybe you snipped it when posting.

    InterBase expects that you will handle any exceptions raised by your UDF. Invoking COM in a UDF isn't a great idea, but doing it without explicitly handling exceptions and checking for COM errors is wildly dangerous. IMHO you should decide what your function should return when there is an error and explicitly code that.

    Again, debugging through the Delphi DLL will make this a lot easier to understand.

    In recent versions of InterBase (can't remember if this started in 6 or 7, but it's one of those) UDFs must be in the UDF folder, not lib, unless you change the default in the ibconfig file. If you have your DLL in both places, IB might not be finding the one you expect.

    I wrote an article on the subject years ago; it's a bit out of date now, but may answer some of your questions.
    Wednesday, March 12, 2008 2:40 PM
  • thanks a lot for the quick response. i'll see your article. i forgot to mention that i'm using intrBase 5.6, so your article is perfect. The only thing i didn't understand is what is CoInitialize?
    Wednesday, March 12, 2008 2:50 PM
  • CoInitialize and CoInitializeEx are part of the Windows API. You must call one of them before doing anything with COM. In some cases, though, Delphi will do this for you. It's pretty easy to figure out when you do and don't need to call it. If you need to call it and you forget to do so, you'll get a runtime error that "CoInitialize has not been called." If you don't need to call it (because Delphi has done it for you, based on what is in your project), you'll get an error to that effect, too.
    Wednesday, March 12, 2008 2:56 PM
  • thanks a lot for the help. i'll try managing the problem. i hope i can ask you something if i have any more questions Smile
    Wednesday, March 12, 2008 3:10 PM
  • i still can't get it working. do i have to set ismultithreading to true and if i have to where do i have to do it? i'm in a deadend, please help
    Friday, March 14, 2008 2:46 PM
  • Yes, you must set IsMultiThread (not IsMultiThreading) true. I do it in the initialization section of the unit, as shown in the article. However, I doubt this has anything to do with the problems you describe above.
    Friday, March 14, 2008 2:57 PM
  • Craig,

    sorry to piggy back this thread but you seem like a really knowledgeable guy when it comes to Interbase UDF's.

    I'm looking to create a UDF that given a UTC timestamp and region (this could be a hard coded integer or a string) will return a local timestamp.

    I'm really a PHP developer and haven't properly coded in Delphi for a good four years.  Also, the latest version of Delphi that I have is 5!  We have had some success in creating our own UDF's but I cannot find any delphi/windows function to fulfil my requirements.

    I have searched the .NET framework and have found a function called TimeZoneInfo.ConvertTimeFromUtc.  It gives me exactly what I want!

    So, my question is can I call methods of the .NET framework from either a current version of Delphi (with .NET capabilities) or Visual Studio?

    Any pointers or advice would be really appreciated!

    Thanks
    Tuesday, January 12, 2010 3:10 PM