I have been working with .Net for a client to create a COM control to be used in his clarion product over the last 3 years.
For the most part it has been very successful and I have even shared some of my findings with Clarion Live
One of the things that I thought was impossible to achieve based on other articles I had read was that it is not possible with a standard OLE control to be able to pass a clarion group to the control, until last week I still held this belief.
However after a conversation I had with @MarkGoldberg on Skype, I started to experiment, and within a week I now have quite a good understanding of how to achieve the goal.
The .net code I write here is in C# and you will have to salt to taste for any other .net language.
Firstly though, I think it best to talk data types, From my experimentation I have found I am not able to use all of clarions data types.The following list are the data types I have had success with, but I would need to experiment more to see what else I find, also I have not had a need to test all of clarion’s types, and maybe if you do find these articles useful if you find others, let me know.
CLARION .NET
LONG int
BYTE byte
REAL double
CSTRING(x) string *See later info
DATE clarion date struct, see below
TIME clarion time struct, see below
To match a DATE and TIME type I created two structures in .Net:
namespace Clarion.DataTypes {
public struct ClarionDate {
byte day;
byte month;
ushort year;
}
public struct ClarionTime {
byte hs;
byte seconds;
byte minutes;
byte hour;
}
}
I have put these in a Clarion.DataTypes
namespace, so that it is easy to reference in my projects.
The next thing you will probably want to do in your .Net project is create a struct to map against a group you want to work with. The following is a simple clarion group I will use to show how to define your structures in .net
TestGroup GROUP
LongField LONG
ByteField BYTE
StringField CSTRING(101)
DateField DATE
TimeField TIME
RealField REAL
FinalString CSTRING(51)
END
The structure in .net would look like this.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TestStruct {
int LongField;
byte ByteField;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 101)]
string StringField;
ClarionDate DateField;
ClarionTime TimeField;
double RealField;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 51)]
string FinalString;
}
The first thing to note is the MetaData tags used in the structure, they are from the System.Runtime.InteropServices
name space and you will need to reference that in your class and add a using statement.
The following tag, StructLayout(LayoutKind.Sequential, Pack = 1)]
Is telling the c# compiler that we are going to create a sequential structure and that we want to pack the structure in such a way that each byte will follow the previous one. Obviously as a com control being used in clarion is going to be a 32 com control, the project will have already indicated this (see videos on clarion live).
So now we have instructed the compiler to make our structure layout in the same way that clarion group’s are laid out, and that each byte will follow the last one, in exactly the same way that a clarion group works.
The next MetaData tag of importance is the one proceeding strings. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 101)]
This tag tells the compiler to expect an unmanaged string and the size of that string (in this case 101 bytes).
As mentioned before I am passing CSTRINGS
over rather than a clarion STRING
's, and this is because the .Net string is expecting a /0 terminated string. You may have success passing a clarion STRING
however I am not sure what size you should tell the compiler it is.
In the next post, I will explain how we can then pass the address of our GROUP
over to .net and get .net to reference the pointed to group.