views:

45

answers:

2

I've been given the assignment to port some library routines to C# so our other application developers can access it, but I don't know how to declare the variables so they come into the routine correctly.

The problem is, when I step through reading the input in with the C++ code, I get all skewed values

Attempt to use:

double[] Par = { 8, 16, 8, 0.61, 0.00635, ... }; // 29 variables
double[] Inlet = { 22.18, 43.31, 1.13, 2.81, 0.43 }; // 5 variables
double[] Outlet = { 0, 0, 0, 0, 0, 0 }; // placeholder for 6 variables
SteadyFor(ref Par, ref Inlet, ref Outlet, FileIn, FileOut);

The DLL Import

[DllImport(MODELAPP, EntryPoint = "SteadyFor", ExactSpelling = false)]
public static extern int SteadyFor(
  ref double[] par, ref double[] inlet, ref double[] outlet,
  [MarshalAs(UnmanagedType.LPStr)] string input,
  [MarshalAs(UnmanagedType.LPStr)] string output);

The C++ file:

extern "C" int SteadyFor(double Par[], double Inlet[], double Outlet[], char* FileIn, char* FileOut)
{
  int n = (int)Par[0]; // Actual Reading: [0]
  int nt = (int)Par[1]; // Actual Reading: [0]
  int pass = (int)Par[2]; // Actual Reading: [0]
  double l = Par[3]; // Actual Reading: [2.9581223236733198e+174]
  double rTube = Par[4]; // Actual Reading: [2.121995790965e-314#DEN]
  double tTube = Par[5]; // Actual Reading: [5.432309224896e-312#DEN]
  double pl = Par[6]; // Actual Reading: [1.0253217546256438e-267]
  double pt = Par[7]; // Actual Reading: [4.60629e-308]
  // ...
}

Obviously, the values I am getting are all wrong - almost like non-initialized memory.

Could someone tell me what I'm doing wrong and how to fix it?

Regards,

~Joe

+1  A: 

Basically you need to declare a marshalling attribute. In your case, it would be a MarshalAs(UnmanagedType.LPArray) attribute.

Look here:
http://msdn.microsoft.com/en-us/library/z6cfh6e6%28VS.80%29.aspx#cpcondefaultmarshalingforarraysanchor3

code4life
Our proxy at work is unable to parse the MSDN sites. I'll look into this later. For now, I'm just going to code with your answer! Thanks.
jp2code
@jp2code, I hope your locally installed MSDN works...!
code4life
Rats. That did not work. All values still come in with integers being zeros and doubles being something freaky.
jp2code
+3  A: 

Drop the "ref" keywords in the declaration, they are not correct. That the C++ code doesn't crash with an AV is a bit mysterious.

The [MarshalAs] attribute on the strings is unnecessary.

Hans Passant
That worked, Hans. Now, why? C++ is bringing in pointers, and C# is passing ...what? Pointers?
jp2code
The default marshaling for an array is passing a pointer to its first element. Just like C++ does. Arrays are never passed by value, that would be horribly expensive and doomed to fail on large arrays. When you use "ref" it passes a pointer to that pointer.
Hans Passant