views:

673

answers:

2

This is my first attempt to call a .NET assembly from a Delphi 5 (Win32) native assembly. I am only familiar with C# and .NET so please bear with me. I guess I will walk thru this layer by layer. Here is the code for the C# assembly I am attempting to execute from the Delphi 5 assembly.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.Linq;
using System.IO;

namespace Company.Program.Utils.Xml
{
    public class XmlExtensions
    {
        public XmlExtensions(){ 
     }

        public static void Transform(string XmlPath, string XsltPath) 
        {

            MessageBox.Show(string.Format("{0}\n{1}",XmlPath, XsltPath));

            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(XsltFile);

            MessageBox.Show("Done.");

        }
    }
}

I have wrapped the static method above with a C++/CLI assembly. Here is header file for the “IL-Bridge” portion of the C++/CLI assembly.

#pragma once
#pragma managed

using namespace Company::Program::Utils::Xml;

void ILBridge_XmlFunc(wchar_t *first, wchar_t *second)
{
    System::String^ __Param_first = gcnew System::String(first);
    System::String^ __Param_second = gcnew System::String(second);
    XmlExtensions::Transform(__Param_first, __Param_second);
}

Here is the header file of the unmanaged portion of the C++/CLI assembly. Note this is also the portion that is intended to be callable from the Delphi 5 assembly (Win32).

#pragma once
#pragma unmanaged

extern "C"{
__declspec(dllexport) public void TransformXml(wchar_t *XmlPath, wchar_t *XsltPath);
}

Here is the implementation of the previous header files. Note one portion is managed and the other unmanaged.

#include "stdafx.h"

#pragma managed
#include "ILBridge_XmlFunc.h"
#pragma unmanaged
#include "XmlTransform.h"

void TransformXml(wchar_t *XmlPath, wchar_t *XsltPath)
{
    ILBridge_XmlFunc(XmlPath, XsltPath);
}

Finally here is the code for the Delphi 5 assembly utilizing the compiled C++/CLI assembly. The C++/CLI compiled DLL is named XmlUtils.dll

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
        { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TransformXml(XmlPath, XsltPath: PWideChar); cdecl; external 'XmlUtils.dll';

procedure TForm1.Button1Click(Sender: TObject);
 var
   str1, str2 : PWideChar;
 begin
   str1 := 'C:\\Users\\Public\\data.xml';
   str2 := 'C:\\Users\\Public\\transform.xslt';
   TransformXml(str1, str2);
end;

end.

I am successful in calling the .NET assembly with the code above. If you go back to the first set of code (the C# code), the first line ran in the function is…

MessageBox.Show(string.Format("{0}\n{1}",XmlPath, XsltPath));

which runs successfully and shows the strings have been passed correctly. It isn’t until I hit this line…

xslt.Load(XsltFile);

of the C# code I get an External Exception Error from Delphi’s just-in-time debugger. The error says “Exception E0434F4D”. Can you guys help me troubleshoot this and explain its origin?

Edit: The exception thrown from the .NET DLL is a System Arithmetic Exception. Again, this only happens when called from the Delphi DLL. If I catch the exception in the .NET DLL and just run xslt.Load(XsltFile) again (in the catch block) it seems to run fine.

+1  A: 
Paul-Jan
+1 for the "native Win32 assembly" comment. We *know* what "assembly" is, and it's about the furthest thing from managed code that you can possibly find. :P
Mason Wheeler
I've got three words for you: ctrl. alt. c. Debugging Delphi wouldn't be the same without it. :D
Paul-Jan
+1  A: 

Maybe you suffer from differences in the Floating-Point Control Register as stated here. Also see this QC report. You could try calling Set8087CW($133F); in your Delphi program. Be cautious of floating point problems in your Delphi code after that.

Lars Truijens
I really appreciate your help. Thank you!
beef