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.