random thoughts, formed in the twisted mind of a coder... RSS 2.0
# Sunday, January 25, 2009

When I wrote the article "Marshalling: Using native DLLs in .NET", I had no clue that so many people have problems using native DLLs in managed code. I receive comments and email very frequently about this topic. Most of the times people ask me to help them writing the C# code that does the import of the unmanaged DLL.

To keep the story short... I'm in the process of writing a Marshalling Compiler (of some sort). It's an online compiler which takes a C style header as input and delivers C# code as output. This C# output code consists of function imports, struct definitions and enum definitions.

Know that it's not a perfect compiler and it probably never will be. Though I'll try to keep improving the functionality until most people can use it.

Go to the Marshalling Compiler

For more information on Marshalling in general, please read "Marshalling: Using native DLLs in .NET"

If you encounter any errors which shouldn't occur, please post your comments on this page. But before you do, please first check if your C style header is correct and please also check that the error wasn't reported by someone else.

 

version 0beta1:

This is the initial version on the web. It converts a C style header, but the output is simple. It still lacks the generation of code that will dereference pointers and so. Please use it to test it. There is also a test header file for download at the compiler page.

 

Sunday, January 25, 2009 3:11:54 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [9]
.Net | Marshalling
Tuesday, February 17, 2009 9:06:53 AM (W. Europe Standard Time, UTC+01:00)
Ashish Jain, has found a bug in the Marshalling Compiler.

The compiler always declares the class containing the imports like this:

public class Imported
{

This is of course flawed when using unsafe types or references. The class should be declared like this:

internal unsafe class Imported
{

You could omit the "internal" modifier, but it would be wise to use it in a clean-coding-kind-of-way... ish..
Tuesday, April 21, 2009 3:39:59 PM (W. Europe Daylight Time, UTC+02:00)
I tried to use your compiler (to call a legacy dll) but it failed with the message:
#0: Error: 'The compiler does not support the use of nested arrays with an assigned depth. Invalid examples are: int[10][11], int[10][]. Valid examples are: int[10], int[], int[][10]'

The header-file I tried with was:

struct structSeasonCoeffs
{
float fDUD[4][5][12][5];
float fFAM[4][14][12];
float fFAKP[4][29][16][6];
float fFAKABP[4][2][6];
float fVDARRAY[4][5][12][2];
};

struct structIonosphereData
{
int nKA[9][20];
float fUU1[9][13][76];
float fUU2[9][13][76];
};

void File2StructNoiseData(char *path, structSeasonCoeffs* pSeasonCoeffs);

void File2StructIonosphereData(char *path, int nMonth, structIonosphereData* pstIonsphereData);


I have managed to call the first method (File2StructNoiseData), with success, with this C# code:
[StructLayout(LayoutKind.Sequential)]
public struct structSeasonCoeffs
{
unsafe fixed float fDUD[1200]; // float[4, 5, 12, 5]
unsafe fixed float fFAM[672]; // float[4,14,12]
unsafe fixed float fFAKP[11136]; // float[4,29,16,6]
unsafe fixed float fFAKABP[48]; // float[4,2,6]
unsafe fixed float fVDARRAY[480]; // float[4,5,12,2]
};

[DllImport(@"C:\Projekt\TCT\src\Straca\vendor\HF\readHF.dll", EntryPoint=@"?File2StructNoiseData@@YAXPADPAUstructSeasonCoeffs@@@Z", CharSet=CharSet.Auto, SetLastError=true)]
private unsafe static extern void File2StructNoiseData([MarshalAs(UnmanagedType.LPStr)] StringBuilder path,
ref structSeasonCoeffs pSeasonCoeffs);

structSeasonCoeffs _pstSeasonCoeffs = new structSeasonCoeffs();
StringBuilder sb = new StringBuilder(path + @"\HFCalculationData\Noisedat\");
File2StructNoiseData(sb, ref _pstSeasonCoeffs);

But when I try the same (almost) with the other one (C#):
[StructLayout(LayoutKind.Sequential, Size=17964)]
public struct structIonosphereData
{
unsafe fixed int nKA[180]; // int[9, 20]
unsafe fixed float fUU1[8892]; // float[9, 13, 76]
unsafe fixed float fUU2[8892]; // float[9, 13, 76]
};

[DllImport(@"C:\Projekt\TCT\src\Straca\vendor\HF\readHF.dll", EntryPoint=@"?File2StructIonosphereData@@YAXPADHPAUstructIonosphereData@@@Z")]
private static extern void File2StructIonosphereData([MarshalAs(UnmanagedType.LPStr)] StringBuilder path, int nMonth, ref structIonosphereData pstIonsphereData);

sb = new StringBuilder(path + @"\HFCalculationData\Ionosphere\");
structIonosphereData pstIonosphereData = new structIonosphereData();
File2StructIonosphereData(sb, 3, ref pstIonosphereData);


Then I get this exception: MarshalDirectiveException with message "Cannot marshal 'parameter #3': Internal limitation: structure is too complex or too large."

What is the problem? Is there some kind of limit at 16Kb? Why? And how can I get around it? The first struct is ~15.5Kb and the second is ~18Kb. Or can't I multiply the dimensions together ([9][13][76] --> [8892])? It seems to work fine with the first struct.

Please help if you can!
Best regards,
Andreas

(sorry about the spaces/indentation, don't know how to get it more readable)
Andreas
Wednesday, April 22, 2009 9:11:44 AM (W. Europe Daylight Time, UTC+02:00)
Hi Andreas,

You might want to compile your header like this:

-----------------------------

struct structSeasonCoeffs
{
float fDUD[][][][5];
float fFAM[][][12];
float fFAKP[][][][6];
float fFAKABP[][][6];
float fVDARRAY[][][][2];
};

struct structIonosphereData
{
int nKA[][20];
float fUU1[][][76];
float fUU2[][][76];
};

extern void File2StructNoiseData(char *path, structSeasonCoeffs* pSeasonCoeffs);

extern void File2StructIonosphereData(char *path, int nMonth, structIonosphereData* pstIonsphereData);

-----------------------------

It results in the following code:

-----------------------------

using System;
using System.Runtime.InteropServices;

public class Imported
{

[StructLayout(LayoutKind.Explicit, Size=124)]
public struct structSeasonCoeffs
{
[FieldOffset(0)] void*[] fDUD;
[FieldOffset(20)] void*[] fFAM;
[FieldOffset(68)] void*[] fFAKP;
[FieldOffset(92)] void*[] fFAKABP;
[FieldOffset(116)] void*[] fVDARRAY;
}

[StructLayout(LayoutKind.Explicit, Size=688)]
public struct structIonosphereData
{
[FieldOffset(0)] void*[] nKA;
[FieldOffset(80)] void*[] fUU1;
[FieldOffset(384)] void*[] fUU2;
}

[DllImport(path_to_dll)]
public static extern void File2StructNoiseData([MarshalAs(LPStr)] string path, void* pSeasonCoeffs);

[DllImport(path_to_dll)]
public static extern void File2StructIonosphereData([MarshalAs(LPStr)] string path, int nMonth, void* pstIonsphereData);

}

-----------------------------

Now, you'll probably get some memory errors when you run this, because in the header file I stripped all nested arrays with a fixed size.
So what you have to do now, is count all the bytes and manually adapt the C# code.

For example, the line:
. float fDUD[4][5][12][5];

contains 4 pointers to 5 pointers to 12 pointers to 5 floats
Now, a float takes 4 bytes and on a 32 bit system, a pointer also takes 4 bytes.
This means that you have 4*5*12*5*4 = 4800 bytes

And if you look at the C# code:
. [FieldOffset(0)] void*[] fDUD;
. [FieldOffset(20)] void*[] fFAM;

You see that you have to change the field offset of fFAM to 4800. And so on for every field.
Also you have to change the line:
. [StructLayout(LayoutKind.Explicit, Size=124)]

Change the Size to the total number of bytes of the complete struct.

Though, now the really hard part is... how are you going to reconstruct your floats from the nested arrays?


Thursday, April 23, 2009 1:46:56 PM (W. Europe Daylight Time, UTC+02:00)
Thank you for your help! It helped me to find the problem. There where two problems:

* I had incorrectly multiplied the number of floats to Size=17964 and forgot to multiply with 4 (the size of the float itself!)
* I used ref structIonosphereData pstIonsphereData instead of void* pstIonsphereData in the function call

After that both calls worked!

But one new problem appeared. The second function should be called 12 times, one for each month. And therefore create 12 different structs with data. Something like this:

structIonosphereData[] pstIonosphereDataList = new structIonosphereData[12];
for(int i = 1; i <= 12; i++) {
File2StructIonosphereData(path + @"\HFCalculationData\Ionosphere\", i, &pstIonosphereDataList[i]);
}

But this doesn't work. I can't create an array for 12 different structs with fixed values. I tried different approaches but nothing seems to work. Any idéas?

Best regards,
Andreas
Andreas
Friday, April 24, 2009 11:08:49 AM (W. Europe Daylight Time, UTC+02:00)
Hi Andreas,

Does the function File2StructIonosphereData create a structure (allocates memory), or does it fill a passed structure with data?
If the last is the case, then you still need to create the structure in C#. In your code you've only created an array, but not the structure types yet.

Furthermore, you could probably better use an IntPtr instead of &pstIonosphereDataList[i].
Please read an other article of me: http://blog.rednael.com/2008/08/29/MarshallingUsingNativeDLLsInNET.aspx
There is a special edit where I explain on how to pass structures.


Tuesday, July 14, 2009 9:02:11 PM (W. Europe Daylight Time, UTC+02:00)
I am trying to add a dll written for c++ to communicate and control a motor. I have very little expereince with the ins and outs of both c++ or c# but that is what was requested I use. I tried using the compiler with the following code.

do I need to create a new class?
I Am not quite sure how to implement your tutorial on the following. an example or guidance would be very helpful.

Thanks

*********************************************************************
** maxon motor ag, CH-6072 Sachseln
**********************************************************************
**
** File: Definitions.h
** Description: Functions definitions for EposCmd.dll library for
** Developer Platform Microsoft Visual C++
**
** Date: 20.10.03
** Dev. Platform: Microsoft Visual C++ 6.0
** Target: Win9x, WinNT, Win2000 and WinXP
** Written by: Adrian Ineichen, maxon motor ag, CH-6072 Sachseln
**
** Changes: 1.00 (20.10.03): Initial Version
** 1.01 (01.12.03): Changed Functions: VCS_GetDeviceNameSelection, BOOL VCS_GetDeviceName,
** VCS_GetProtocolStackNameSelection, VCS_GetInterfaceNameSelection, VCS_GetPortNameSelection,
** VCS_GetBaudrateSelection, VCS_GetProtocolStackModeSelection, VCS_GetProtocolStackName,
** VCS_GetInterfaceName, VCS_GetPortName
** 1.1.0.0 (13.01.04): If the functions GetXXXSelection were alone called,
** no manager was initialized. Again an inquiry inserted
** (21.01.04): New Functions: VCS_CloseAllDevices, VCS_DigitalInputConfiguration,
** VCS_DigitalOutputConfiguration, VCS_GetAllDigitalInputs, VCS_GetAllDigitalOutputs,
** VCS_GetAnalogInput, VCS_SetAllDigitalOutputs
** (29.03.04): New Functions: VCS_OpenDeviceDlg, SendNMTService
** Changed Functions: VCS_OpenDevice, VCS_SetObject, VCS_GetObject, VCS_FindHome, VCS_SetOperationMode, VCS_GetOperationMode, VCS_MoveToPosition
** Deleted Functions: VCS_GetProtocolStackMode, VCS_GetProtocolStackModeSelection
** 2.0.0.0 (07.04.04): Release Version
** 2.0.1.0 (13.04.04): Bugfix Version
** 2.0.2.0 (15.04.04): Bugfix Version
** 2.0.3.0 (11.05.04): Bugfix Version
** (07.12.04): New Functions: VCS_SendCANFrame,VCS_RequestCANFrame
** 3.0.0.0 (31.03.05): All EPOS - functions => new with the handle for the Journal
** New Functions: VCS_StartJournal,VCS_StopJournal
** 3.0.1.0 (08.03.05): Internal Version
** 3.0.2.0 (09.09.05): BugFix: 1 IXXAT board with 2 ports
** 4.0.0.0 (21.10.05): Release Version
** 4.1.0.0 (02.02.06): New DLL structure (Dtms and GUI Version 2.01)
** 4.1.1.0 (12.04.06): Internal Version
** 4.1.2.0 (12.06.06): Internal Version
** 4.1.3.0 (03.07.06): Internal Version (GUI Version 2.04)
** 4.1.4.0 (16.08.06): LSS functions implemented
** 4.2.0.0 (12.10.06): Customer Version
** 4.3.0.0 (01.02.07): Support for National Instruments Interfaces
** 4.4.0.0 (10.08.07): New driver (V3) for CANopen cards from IXXAT
** 4.5.0.0 (01.05.08): Converted to development environment Visual Studio 2005
** Read device error history (VCS_GetNbOfDeviceError, VCS_GetDeviceErrorCode)
**
*********************************************************************/

// --------------------------------------------------------------------------
// IMPORTED FUNCTIONS PROTOTYPE
// --------------------------------------------------------------------------

#define Initialisation_DllExport extern "C" __declspec( dllexport )
#define HelpFunctions_DllExport extern "C" __declspec( dllexport )
#define Configuration_DllExport extern "C" __declspec( dllexport )
#define CurrentMode_DllExport extern "C" __declspec( dllexport )
#define HomingMode_DllExport extern "C" __declspec( dllexport )
#define InputsOutputs_DllExport extern "C" __declspec( dllexport )
#define MotionInfo_DllExport extern "C" __declspec( dllexport )
#define PositionMode_DllExport extern "C" __declspec( dllexport )
#define StateMachine_DllExport extern "C" __declspec( dllexport )
#define Utilities_DllExport extern "C" __declspec( dllexport )
#define ProfileVelocityMode_DllExport extern "C" __declspec( dllexport )
#define VelocityMode_DllExport extern "C" __declspec( dllexport )
#define ProfilePositionMode_DllExport extern "C" __declspec( dllexport )
#define GeneralGateway_DllExport extern "C" __declspec( dllexport )

#define DialogLayer_DllExport extern "C" __declspec( dllexport )

//Initialisation
Initialisation_DllExport HANDLE __stdcall VCS_OpenDevice(char* DeviceName, char* ProtocolStackName, char* InterfaceName, char* PortName, DWORD* pErrorCode);
Initialisation_DllExport BOOL __stdcall VCS_CloseDevice(HANDLE KeyHandle, DWORD* pErrorCode);
Initialisation_DllExport BOOL __stdcall VCS_CloseAllDevices(DWORD* pErrorCode);
Initialisation_DllExport BOOL __stdcall VCS_GetProtocolStackSettings(HANDLE KeyHandle, DWORD* pBaudrate, DWORD* pTimeout, DWORD* pErrorCode);
Initialisation_DllExport BOOL __stdcall VCS_SetProtocolStackSettings(HANDLE KeyHandle, DWORD Baudrate, DWORD Timeout, DWORD* pErrorCode);

//Help functions
HelpFunctions_DllExport BOOL __stdcall VCS_GetBaudrateSelection(char* DeviceName, char* ProtocolStackName, char* InterfaceName, char* PortName, BOOL StartOfSelection, DWORD* pBaudrateSel, BOOL* pEndOfSelection, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetDeviceName(HANDLE KeyHandle, char* pDeviceName, WORD MaxStrSize, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetDeviceNameSelection(BOOL StartOfSelection, char* pDeviceNameSel, WORD MaxStrSize, BOOL* pEndOfSelection, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetDriverInfo(char* pLibraryName, WORD MaxNameSize, char* pLibraryVersion, WORD MaxVersionSize, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetInterfaceName(HANDLE KeyHandle, char* pInterfaceName, WORD MaxStrSize, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetInterfaceNameSelection(char* DeviceName, char* ProtocolStackName, BOOL StartOfSelection, char* pInterfaceNameSel, WORD MaxStrSize, BOOL* pEndOfSelection, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetKeyHandle(char* DeviceName, char* ProtocolStackName, char* InterfaceName, char* PortName, HANDLE* pKeyHandle, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetPortName(HANDLE KeyHandle, char* pPortName, WORD MaxStrSize, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetPortNameSelection(char* DeviceName, char* ProtocolStackName, char* InterfaceName, BOOL StartOfSelection, char* pPortSel, WORD MaxStrSize, BOOL* pEndOfSelection, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetProtocolStackName(HANDLE KeyHandle, char* pProtocolStackName, WORD MaxStrSize, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetProtocolStackNameSelection(char* DeviceName, BOOL StartOfSelection, char* pProtocolStackNameSel, WORD MaxStrSize, BOOL* pEndOfSelection, DWORD* pErrorCode);
HelpFunctions_DllExport BOOL __stdcall VCS_GetErrorInfo(DWORD ErrorCodeValue, char* pErrorInfo, WORD MaxStrSize);

//Configuration
Configuration_DllExport BOOL __stdcall VCS_GetCurrentRegulatorGain(HANDLE KeyHandle, WORD NodeId, WORD* pP, WORD* pI, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_GetEncoderParameter(HANDLE KeyHandle, WORD NodeId, WORD* pCounts, WORD* pPositionSensorType, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_GetMotorParameter(HANDLE KeyHandle, WORD NodeId, WORD* pMotorType, WORD* pContinuousCurrent, WORD* pPeakCurrent, BYTE* pPolePair, WORD* pThermalTimeConstant, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_GetPositionRegulatorGain(HANDLE KeyHandle, WORD NodeId, WORD* pP, WORD* pI, WORD* pD, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_GetVelocityRegulatorGain(HANDLE KeyHandle, WORD NodeId, WORD* pP, WORD* pI, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_SetCurrentRegulatorGain(HANDLE KeyHandle, WORD NodeId, WORD P, WORD I, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_SetEncoderParameter(HANDLE KeyHandle, WORD NodeId, WORD Counts, WORD PositionSensorType, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_SetMotorParameter(HANDLE KeyHandle, WORD NodeId, WORD MotorType, WORD ContinuousCurrent, WORD PeakCurrent, BYTE PolePair, WORD ThermalTimeConstant, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_SetPositionRegulatorGain(HANDLE KeyHandle, WORD NodeId, WORD P, WORD I, WORD D, DWORD* pErrorCode);
Configuration_DllExport BOOL __stdcall VCS_SetVelocityRegulatorGain(HANDLE KeyHandle, WORD NodeId, WORD P, WORD I, DWORD* pErrorCode);

//Current Mode
CurrentMode_DllExport BOOL __stdcall VCS_GetCurrentMust(HANDLE KeyHandle, WORD NodeId, short* pCurrentMust, DWORD* pErrorCode);
CurrentMode_DllExport BOOL __stdcall VCS_SetCurrentMust(HANDLE KeyHandle, WORD NodeId, short CurrentMust, DWORD* pErrorCode);

//Homing Mode
HomingMode_DllExport BOOL __stdcall VCS_FindHome(HANDLE KeyHandle, WORD NodeId, __int8 HomingMethod, DWORD* pErrorCode);
HomingMode_DllExport BOOL __stdcall VCS_GetHomingParameter(HANDLE KeyHandle, WORD NodeId, DWORD* pHomingAcceleration, DWORD* pSpeedSwitch, DWORD* pSpeedIndex, long* pHomeOffset, WORD* pCurrentTreshold, long* pHomePosition, DWORD* pErrorCode);
HomingMode_DllExport BOOL __stdcall VCS_SetHomingParameter(HANDLE KeyHandle, WORD NodeId, DWORD HomingAcceleration, DWORD SpeedSwitch, DWORD SpeedIndex, long HomeOffset, WORD CurrentTreshold, long HomePosition, DWORD* pErrorCode);
HomingMode_DllExport BOOL __stdcall VCS_StopHoming(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);

//Inputs Outputs
InputsOutputs_DllExport BOOL __stdcall VCS_DigitalInputConfiguration(HANDLE KeyHandle, WORD NodeId, WORD DigInputNb, WORD Configuration, BOOL Mask, BOOL Polarity, BOOL ExecutionMask, DWORD* pErrorCode);
InputsOutputs_DllExport BOOL __stdcall VCS_DigitalOutputConfiguration(HANDLE KeyHandle, WORD NodeId, WORD DigOutputNb, WORD wConfiguration, BOOL State, BOOL Mask, BOOL Polarity, DWORD* pErrorCode);
InputsOutputs_DllExport BOOL __stdcall VCS_GetAllDigitalInputs(HANDLE KeyHandle, WORD NodeId, WORD* pInputs, DWORD* pErrorCode);
InputsOutputs_DllExport BOOL __stdcall VCS_GetAllDigitalOutputs(HANDLE KeyHandle, WORD NodeId, WORD* pOutputs, DWORD* pErrorCode);
InputsOutputs_DllExport BOOL __stdcall VCS_SetAllDigitalOutputs(HANDLE KeyHandle, WORD NodeId, WORD Outputs, DWORD* pErrorCode);
InputsOutputs_DllExport BOOL __stdcall VCS_GetAnalogInput(HANDLE KeyHandle, WORD NodeId, WORD Number, WORD* pAnalog, DWORD* pErrorCode);

//Motion Info
MotionInfo_DllExport BOOL __stdcall VCS_GetCurrentIs(HANDLE KeyHandle, WORD NodeId, short* pCurrentIs, DWORD* pErrorCode);
MotionInfo_DllExport BOOL __stdcall VCS_GetMovementState(HANDLE KeyHandle, WORD NodeId, BOOL* pTargetReached, DWORD* pErrorCode);
MotionInfo_DllExport BOOL __stdcall VCS_GetPositionIs(HANDLE KeyHandle, WORD NodeId, long* pPositionIs, DWORD* pErrorCode);
MotionInfo_DllExport BOOL __stdcall VCS_GetVelocityIs(HANDLE KeyHandle, WORD NodeId, long* pVelocityIs, DWORD* pErrorCode);

//Position Mode
PositionMode_DllExport BOOL __stdcall VCS_GetPositionMust(HANDLE KeyHandle, WORD NodeId, long* pPositionMust, DWORD* pErrorCode);
PositionMode_DllExport BOOL __stdcall VCS_SetPositionMust(HANDLE KeyHandle, WORD NodeId, long PositionMust, DWORD* pErrorCode);

//Profile Position Mode
ProfilePositionMode_DllExport BOOL __stdcall VCS_HaltPositionMovement(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);
ProfilePositionMode_DllExport BOOL __stdcall VCS_MoveToPosition(HANDLE KeyHandle, WORD NodeId, long TargetPosition, BOOL Absolute, BOOL Immediately, DWORD* pErrorCode);
ProfilePositionMode_DllExport BOOL __stdcall VCS_GetTargetPosition(HANDLE KeyHandle, WORD NodeId, long* pTargetPosition, DWORD* pErrorCode);
ProfilePositionMode_DllExport BOOL __stdcall VCS_GetPositionProfile(HANDLE KeyHandle, WORD NodeId, DWORD* pProfileVelocity, DWORD* pProfileAcceleration, DWORD* pProfileDeceleration, DWORD* pErrorCode);
ProfilePositionMode_DllExport BOOL __stdcall VCS_SetPositionProfile(HANDLE KeyHandle, WORD NodeId, DWORD ProfileVelocity, DWORD ProfileAcceleration, DWORD ProfileDeceleration, DWORD* pErrorCode);

//Profile Velocity Mode
ProfileVelocityMode_DllExport BOOL __stdcall VCS_HaltVelocityMovement(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);
ProfileVelocityMode_DllExport BOOL __stdcall VCS_MoveWithVelocity(HANDLE KeyHandle, WORD NodeId, long TargetVelocity, DWORD* pErrorCode);
ProfileVelocityMode_DllExport BOOL __stdcall VCS_GetTargetVelocity(HANDLE KeyHandle, WORD NodeId, long* pTargetVelocity, DWORD* pErrorCode);
ProfileVelocityMode_DllExport BOOL __stdcall VCS_GetVelocityProfile(HANDLE KeyHandle, WORD NodeId, DWORD* pProfileAcceleration, DWORD* pProfileDeceleration, DWORD* pErrorCode);
ProfileVelocityMode_DllExport BOOL __stdcall VCS_SetVelocityProfile(HANDLE KeyHandle, WORD NodeId, DWORD ProfileAcceleration, DWORD ProfileDeceleration, DWORD* pErrorCode);

//State Machine
StateMachine_DllExport BOOL __stdcall VCS_ClearFault(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_GetDisableState(HANDLE KeyHandle, WORD NodeId, BOOL* pIsDisabled, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_GetEnableState(HANDLE KeyHandle, WORD NodeId, BOOL* pIsEnabled, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_GetFaultState(HANDLE KeyHandle, WORD NodeId, BOOL* pIsInFault, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_GetOperationMode(HANDLE KeyHandle, WORD NodeId, __int8* pMode, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_GetQuickStopState(HANDLE KeyHandle, WORD NodeId, BOOL* pIsQuickStopped, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_SendNMTService(HANDLE KeyHandle, WORD NodeId, WORD CommandSpecifier, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_SetDisableState(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_SetEnableState(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_SetOperationMode(HANDLE KeyHandle, WORD NodeId, __int8 Mode, DWORD* pErrorCode);
StateMachine_DllExport BOOL __stdcall VCS_SetQuickStopState(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);

//Utilities
Utilities_DllExport BOOL __stdcall VCS_GetObject(HANDLE KeyHandle, WORD NodeId, WORD ObjectIndex, BYTE ObjectSubIndex, void* pData, DWORD NbOfBytesToRead, DWORD* pNbOfBytesRead, DWORD* pErrorCode);
Utilities_DllExport BOOL __stdcall VCS_GetVersion(HANDLE KeyHandle, WORD NodeId, WORD* pHardwareVersion, WORD* pSoftwareVersion, WORD* pApplicationNumber, WORD* pApplicationVersion, DWORD* pErrorCode);
Utilities_DllExport BOOL __stdcall VCS_GetNbOfDeviceError(HANDLE KeyHandle, WORD NodeId, BYTE *pNbDeviceError, DWORD *pErrorCode);
Utilities_DllExport BOOL __stdcall VCS_GetDeviceErrorCode(HANDLE KeyHandle, WORD NodeId, BYTE SubIndex, DWORD *pDeviceErrorCode, DWORD *pErrorCode);
Utilities_DllExport BOOL __stdcall VCS_Restore(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);
Utilities_DllExport BOOL __stdcall VCS_SetObject(HANDLE KeyHandle, WORD NodeId, WORD ObjectIndex, BYTE ObjectSubIndex, void* pData, DWORD NbOfBytesToWrite, DWORD* pNbOfBytesWritten, DWORD* pErrorCode);
Utilities_DllExport BOOL __stdcall VCS_Store(HANDLE KeyHandle, WORD NodeId, DWORD* pErrorCode);

//General Gateway
GeneralGateway_DllExport BOOL __stdcall VCS_SendCANFrame(HANDLE KeyHandle, WORD CobID, WORD Length, void* pData, DWORD* pErrorCode);
GeneralGateway_DllExport BOOL __stdcall VCS_RequestCANFrame(HANDLE KeyHandle, WORD CobID, WORD Length, void* pData, DWORD* pErrorCode);

//Velocity Mode
VelocityMode_DllExport BOOL __stdcall VCS_GetVelocityMust(HANDLE KeyHandle, WORD NodeId, long* pVelocityMust, DWORD* pErrorCode);
VelocityMode_DllExport BOOL __stdcall VCS_SetVelocityMust(HANDLE KeyHandle, WORD NodeId, long VelocityMust, DWORD* pErrorCode);


//Dialog Layer
DialogLayer_DllExport HANDLE __stdcall VCS_OpenDeviceDlg(DWORD* pErrorCode);
Monday, January 11, 2010 7:21:45 AM (W. Europe Standard Time, UTC+01:00)
Hi, I really liked your article on the topic. Tried the compiler and got a server runtime error.

If you can take a look at it and give feedback, I'll be much appreciated. - Charles

#define SSTCHAR char
#define SSTINT int
#define SSTREAL double


enum SST_NAIL
{
SST_NAIL_NONE,
SST_NAIL_10D,
SST_NAIL_10D15,
SST_NAIL_16D,
SST_NAIL_16D25,
SST_NAIL_16DPLX,
SST_NAIL_8D,
SST_NAIL_N20A,
SST_NAIL_N20AN,
SST_NAIL_N54A,
SST_NAIL_PRONGS,
SST_NAIL_TAPCON14,
SST_NAIL_TAPCON316,
SST_NAIL_TEARDROP,
SST_NAIL_34MB,
SST_NAIL_SDS14X3,
SST_NAIL_CATALOG,
SST_NAIL_SDS14X45,
SST_NAIL_SDS14X6,
SST_NAIL_TITEN14,
SST_NAIL_12MB,
SST_NAIL_58MB,
SST_NAIL_SDS14X2,
SST_NAIL_RFB4X5,
SST_NAIL_RFB5X5,
SST_NAIL_RFB5X8,
SST_NAIL_SDS14X25,
SST_NAIL_SSTB16,
SST_NAIL_SSTB20,
SST_NAIL_SSTB24,
SST_NAIL_SSTB28,
SST_NAIL_78MB,
SST_NAIL_1MB,
SST_NAIL_8D15,
SST_NAIL_TITEN316X225,
SST_NAIL_SDS14X15,
SST_NAIL_16DSINKER,
SST_NAIL_58ANCHOR,
SST_NAIL_TITEN14X225,
SST_NAIL_SPEC,
SST_NAIL_TITEN14X175,
SST_NAIL_SN8X15,
SST_NAIL_SDS14X175,
SST_NAIL_TTN25214H,
SST_NAIL_TTN38X5HD,
SST_NAIL_34ANCHOR,
SST_NAIL_SSTB14,
SST_NAIL_THDBP,
SST_NAIL_THD37400H,
SST_NAIL_THD62500H,
SST_NAIL_TTN38X4HD,
SST_NAIL_375X30,
SST_NAIL_375X75,
SST_NAIL_4X75,
SST_NAIL_4X90,
SST_NAIL_SDS62X63,
SST_NAIL_SB1X30,
SST_NAIL_SB78X24,
SST_NAIL_SSTB34,
SST_NAIL_SSTB36,
SST_NAIL_RFB5X8SET,
SST_NAIL_RFB5X12SET,
SST_NAIL_SN8X14,
SST_NAIL_16DCL,
SST_NAIL_10DCL
};


enum SSTHGR_MATL
{
SSTHGR_MATL_NONE,
SSTHGR_MATL_SAWN_DF,
SSTHGR_MATL_SAWN_HF,
SSTHGR_MATL_SAWN_SP,
SSTHGR_MATL_SAWN_SPF,
SSTHGR_MATL_TRUSS_DF,
SSTHGR_MATL_TRUSS_HF,
SSTHGR_MATL_TRUSS_SP,
SSTHGR_MATL_TRUSS_SPF,
SSTHGR_MATL_GLULAM_DFSP,
SSTHGR_MATL_IJOIST,
SSTHGR_MATL_IJOIST_DF,
SSTHGR_MATL_LSL,
SSTHGR_MATL_LVL_DFSP,
SSTHGR_MATL_PSL,
SSTHGR_MATL_MASONRY,
SSTHGR_MATL_AAC28,
SSTHGR_MATL_LAC35,
SSTHGR_MATL_DAC70,
SSTHGR_MATL_IJOIST_SPF,
SSTHGR_MATL_GLULAM_SPF,
SSTHGR_MATL_LVL_SPF,
SSTHGR_MATL_TLDF,
SSTHGR_MATL_TLSF,
SSTHGR_MATL_CONCRETE,
SSTHGR_MATL_FTDF,
SSTHGR_MATL_FTSPF,
SSTHGR_MATL_C16,
SSTHGR_MATL_IC24,
SSTHGR_MATL_ILVL33,
SSTHGR_MATL_ILVL38,
SSTHGR_MATL_MW,
SSTHGR_MATL_TR26,
SSTHGR_MATL_IC30,
SSTHGR_MATL_ILVL28,
SSTHGR_MATL_IJOIST_1125,
SSTHGR_MATL_IJOIST_1250,
SSTHGR_MATL_IJOIST_1313,
SSTHGR_MATL_IJOIST_1375,
SSTHGR_MATL_IJOIST_1500,
SSTHGR_MATL_IJOIST_DF_1125,
SSTHGR_MATL_IJOIST_DF_1250,
SSTHGR_MATL_IJOIST_DF_1313,
SSTHGR_MATL_IJOIST_DF_1375,
SSTHGR_MATL_IJOIST_DF_1500,
SSTHGR_MATL_IJOIST_SPF_1500,
SSTHGR_MATL_ORM,
SSTHGR_MATL_LRM,
SSTHGR_MATL_VRH,
SSTHGR_MATL_VRS
};

enum SSTHGR_NAIL
{
SSTHGR_NAIL_NONE,
SSTHGR_NAIL_10D,
SSTHGR_NAIL_10D15,
SSTHGR_NAIL_16D,
SSTHGR_NAIL_16D25,
SSTHGR_NAIL_16DPLX,
SSTHGR_NAIL_8D,
SSTHGR_NAIL_N20A,
SSTHGR_NAIL_N20AN,
SSTHGR_NAIL_N54A,
SSTHGR_NAIL_PRONGS,
SSTHGR_NAIL_TAPCON14,
SSTHGR_NAIL_TAPCON316,
SSTHGR_NAIL_TEARDROP,
SSTHGR_NAIL_34MB,
SSTHGR_NAIL_SDS14X3,
SSTHGR_NAIL_CATALOG,
SSTHGR_NAIL_SDS14X45,
SSTHGR_NAIL_SDS14X6,
SSTHGR_NAIL_TITEN14,
SSTHGR_NAIL_12MB,
SSTHGR_NAIL_58MB,
SSTHGR_NAIL_SDS14X2,
SSTHGR_NAIL_RFB4X5,
SSTHGR_NAIL_RFB5X5,
SSTHGR_NAIL_RFB5X8,
SSTHGR_NAIL_SDS14X25,
SSTHGR_NAIL_SSTB16,
SSTHGR_NAIL_SSTB20,
SSTHGR_NAIL_SSTB24,
SSTHGR_NAIL_SSTB28,
SSTHGR_NAIL_78MB,
SSTHGR_NAIL_1MB,
SSTHGR_NAIL_8D15,
SSTHGR_NAIL_TITEN316X225,
SSTHGR_NAIL_SDS14X15,
SSTHGR_NAIL_16DSINKER,
SSTHGR_NAIL_58ANCHOR,
SSTHGR_NAIL_TITEN14X225,
SSTHGR_NAIL_SPEC,
SSTHGR_NAIL_TITEN14X175,
SSTHGR_NAIL_SN8X15,
SSTHGR_NAIL_SDS14X175,
SSTHGR_NAIL_TTN25214H,
SSTHGR_NAIL_TTN38X5HD,
SSTHGR_NAIL_34ANCHOR,
SSTHGR_NAIL_SSTB14,
SSTHGR_NAIL_THDBP,
SSTHGR_NAIL_THD37400H,
SSTHGR_NAIL_THD62500H,
SSTHGR_NAIL_TTN38X4HD,
SSTHGR_NAIL_375X30,
SSTHGR_NAIL_375X75,
SSTHGR_NAIL_4X75,
SSTHGR_NAIL_4X90,
SSTHGR_NAIL_SDS62X63,
SSTHGR_NAIL_SB1X30,
SSTHGR_NAIL_SB78X24,
SSTHGR_NAIL_SSTB34,
SSTHGR_NAIL_SSTB36,
SSTHGR_NAIL_RFB5X8SET,
SSTHGR_NAIL_RFB5X12SET,
SSTHGR_NAIL_SN8X14,
SSTHGR_NAIL_16DCL,
SSTHGR_NAIL_10DCL
};



enum SSTHGR_SKEW
{
SSTHGR_SKEW_NONE,
SSTHGR_SKEW_LEFT,
SSTHGR_SKEW_RIGHT
};



enum SSTHGR_SLOPE
{
SSTHGR_SLOPE_NONE,
SSTHGR_SLOPE_UP,
SSTHGR_SLOPE_DOWN
};



enum SSTHGR_TFOC
{
SSTHGR_TFOC_NONE,
SSTHGR_TFOC_CLOSED,
SSTHGR_TFOC_OPEN
};



enum SSTHGR_TFSL
{
SSTHGR_TFSL_NONE,
SSTHGR_TFSL_LEFT,
SSTHGR_TFSL_RIGHT
};



enum SSTHGR_TFOS
{
SSTHGR_TFOS_NONE,
SSTHGR_TFOS_LEFT,
SSTHGR_TFOS_RIGHT
};



enum SSTHGR_ANSITPI
{
SSTHGR_ANSITPI_NO,
SSTHGR_ANSITPI_YES,
SSTHGR_ANSITPI_DOUBLE,
SSTHGR_ANSITPI_ENDS,
SSTHGR_ANSITPI_INT
};



enum SSTHGR_STYLE
{
SSTHGR_STYLE_ANY,
SSTHGR_STYLE_FACE,
SSTHGR_STYLE_TF,
SSTHGR_STYLE_CONCEAL,
SSTHGR_STYLE_10D15,
SSTHGR_STYLE_10D,
SSTHGR_STYLE_16D,
SSTHGR_STYLE_SDS
};



enum SSTHGR_SORT
{
SSTHGR_SORT_NONE,
SSTHGR_SORT_MODEL,
SSTHGR_SORT_WSIZE,
SSTHGR_SORT_HSIZE,
SSTHGR_SORT_BSIZE,
SSTHGR_SORT_TFSIZE,
SSTHGR_SORT_HNAIL,
SSTHGR_SORT_JNAIL,
SSTHGR_SORT_TFNAIL,
SSTHGR_SORT_LOAD,
SSTHGR_SORT_UPLIFT,
SSTHGR_SORT_ICI
};



enum SSTHGR_LEDGER
{
SSTHGR_LEDGER_NO,
SSTHGR_LEDGER_YES
};




#define SSTHGR_NOTE_NONE 0x00
#define SSTHGR_NOTE_WSR 0x01




#define SSTHGR_ERROR_OUTPUT -1
#define SSTHGR_ERROR_LOAD -2
#define SSTHGR_ERROR_UPLIFT -3
#define SSTHGR_ERROR_HEADER -4
#define SSTHGR_ERROR_JOIST -5
#define SSTHGR_ERROR_SKEW -6
#define SSTHGR_ERROR_SLOPE -7
#define SSTHGR_ERROR_TF -8
#define SSTHGR_ERROR_ANSITPI -9
#define SSTHGR_ERROR_STYLE -10
#define SSTHGR_ERROR_SORT -11
#define SSTHGR_ERROR_KING -12

#define SSTHGR_ERROR_BALANCE -1001




struct SstHgrIn4
{
SSTINT loadType;
SSTINT upliftType;
SSTHGR_MATL hType;
SSTREAL hWidth;
SSTREAL hHeight;
SSTINT hPly;
SSTHGR_MATL jType[3];
SSTREAL jWidth[3];
SSTREAL jHeight[3];
SSTINT jPly[3];
SSTINT load[3];
SSTINT uplift[3];
SSTREAL skew[3];
SSTHGR_SKEW skewType[3];
SSTREAL slope[3];
SSTHGR_SLOPE slopeType[3];
SSTREAL tfoc;
SSTHGR_TFOC tfocType;
SSTREAL tfsl;
SSTHGR_TFSL tfslType;
SSTHGR_TFOS tfosType;
SSTHGR_ANSITPI ansiTpi;
SSTHGR_STYLE style;
SSTHGR_SORT sort;
SSTREAL kingWidth;
SSTREAL kingHeight;
SSTHGR_LEDGER ledgerType;
};

struct SstHgrOut4
{
SSTCHAR model[25];
SSTCHAR catalog[25];
SSTREAL wSize;
SSTREAL hSize;
SSTREAL bSize;
SSTREAL tfSize;
SSTINT note;
SSTHGR_NAIL hNailType[2];
SSTINT hNailQty[2];
SSTHGR_NAIL jNailType;
SSTINT jNailQty;
SSTHGR_NAIL tfNailType;
SSTINT tfNailQty;
SSTINT load;
SSTINT uplift;
SSTINT ici;
SSTCHAR spec[100];
};


extern "C" SSTINT sstHgrGet4(const SstHgrIn4 &in, SstHgrOut4 *out, const int nOut);
Charles Zhu
Friday, January 29, 2010 1:13:49 PM (W. Europe Standard Time, UTC+01:00)
Hi,
I've one c++ unmanaged dll and two headers (.h). I'd like to write a wrapper for c# project.
I use the Marshalling compiler and i got some problems

1) Marshalling enum
enum UNIPRO_Sex {MALE = '0', FEMALE = '1', SEX_UNKNOWN = '2'}

2) Marshalling struct
typedef struct rhythm_data
{
unsigned short NumberOfBytes;
unsigned char *RhythmData;
} RHYTHM_DATA;

typedef struct sectionG
{
int SectionExists;
RHYTHM_DATA *RhythmData;
} SECTIONG;

3) something wrong in offset count
typedef struct sectionB
{
int SectionExists;
bool LongVersion;
int NumberOfTags;
} SECTIONB;

is wrapped as

[StructLayout(LayoutKind.Explicit, Size=12)]
public struct sectionB
{
[FieldOffset(0)] int SectionExists;
[FieldOffset(4)] [MarshalAs(Bool)] bool LongVersion;
[FieldOffset(8)] int NumberOfTags;
}

A bool isn't equivalent to 1 Byte? I'd expect the following result

[StructLayout(LayoutKind.Explicit, Size=12)]
public struct sectionB
{
[FieldOffset(0)] int SectionExists;
[FieldOffset(4)] [MarshalAs(Bool)] bool LongVersion;
[FieldOffset(5)] int NumberOfTags;
}

How can i solve these issues? Please help me.
pyth
Monday, February 01, 2010 3:37:26 PM (W. Europe Standard Time, UTC+01:00)
Hi pyth,

Just simply check the checkbox below the input field, named: bool-is-one-byte

All comments require the approval of the site owner before being displayed.
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Martijn Thie
Sign In
Statistics
Total Posts: 18
This Year: 0
This Month: 0
This Week: 0
Comments: 142
All Content © 2010, Martijn Thie
DasBlog theme adapted from 'Business' (originally by delarou)