2

It seems like I'm on here asking a question just about every day now. I'm not sure if that's a good thing or a bad thing...

Today's "Flavor-Of-The-WTF" involves my complete and utter cluelessness when using a function from a NI Measurement Studio object. As with most of my previous questions, this is in regards to an internship project where I've been tasked with translating a VB6 project into C# in the .Net Framework 2.0.

The original VB code looks something like this:

Public Sub FFT(ZData() As Single, FFTData() As Single)
    Dim realdata As Variant
    Dim imgdata As Variant

    // (... Some unrelated other code in here ...)

    // Here we pass three variables to a NI CWDSP object's ReFFT function
    CWDSP1.ReFFT ZData, realdata, imgdata

    // (... More unrelated code ...)
End Sub

I stuck in a MsgBox at one point to see how realdata and imgdata were being interpreted. They're both Double()s. It works just fine for what it does, in the original program. Admittedly, my intimate knowledge of the original program is only mediocre, as I picked up the project recently, and only have a few years of programming under my belt (and no years of mechanical engineering. The programmer was a mechanical engineer, the application itself a measuring tool for machine output).

Taking the code over to C#, I tried rewriting it as such:

private void FFT(float[] ZData, float[] FFTData){
    double[] realData = new double[1000];
    double[] imgData = new double[1000];

    // (... Unrelated intermediate code ...)

    DSP.ReFFT(ZData, realData, imgData);

    // (... Unrelated intermediate code ...)
}

As you can see, I started by doing it basically the same way as the original VB. The following error came up: Cannot Convert double[] to ref object

Well, that's no good. So I tried: DSP.ReFFT(ZData, ref realData, ref imgData);

Only to get back: Cannot Convert ref double[] to ref object

So I did what I thought was obvious. I boxed realData and imgData into objects, and passed them to the function. It's not too fond of that, however. If I pass the new objects without ref, it insists that I need to pass them with ref. If I pass them with ref, it gives me the error:

Cannot Convert ref double[] to ref object.

Huh... that looks familiar. I finally get the compiler to stop producing errors when I change double[] to Object in the instantiation of the two variables. But... when I run the function, I get a Type Mismatch error.

I've really got no idea where I go from here. There's little to no information about programming for C# with Measurement Studio out there on the internet. Even if there was, I'm sure the solution is much more simple than I expect it to be. History has taught me that when there's a bug I can't figure out, it's almost always something stupid.

CharlesB
  • 86,532
  • 28
  • 194
  • 218
KChaloux
  • 3,918
  • 6
  • 37
  • 52
  • No, .COM. Sorry for not specifying. – KChaloux Jul 08 '10 at 18:27
  • In the VB6 code what types are `realdata` and `imgdata` actually holding? What is the method signature of the `DSP` class? – Brian Gideon Jul 08 '10 at 18:48
  • Like I said in my (admittedly stupidly long) post, I ran a MsgBox TypeName() and they both came back as arrays of doubles. The signature for the axCWDSP.ReFFT seems to be: `public virtual void ReFFT(object x, ref object y, ref object z);` – KChaloux Jul 08 '10 at 18:54

4 Answers4

3

Give this a go in your FFT function:

object realData = new double[1000];
object imgData = new double[1000];
ReFFT(new object(), ref realData, ref imgData);

double[] realDataArray = (double[])realData;

by instantiating the object as a new double[1000], you are establishing that although you are treating realData as an object, its' underlying type is double[]. Later, after the method call, you're closing the realData array by creating a new one and casting the previous one to the original type. It may be more boxing/unboxing than is strictly needed, but hopefully it gets the point across

Try 2:

double[] somerealData = new double[1000];
double[] someimgData = new double[1000];
object realData, imgData;
realData = somerealData;
imgData = someimgData;

ReFFT(new object(), ref realData, ref imgData);

double[] realDataArray = (double[])realData;
Console.WriteLine(realDataArray.Length);
realDataArray[0] = 1.0d;
Console.WriteLine(realDataArray[0]);

I've tried the second approach in a .NET 2.0 console app, so I'm pretty sure that it works. If it doesn't, then we'll need to take a step back and re-assess the situation.

Try 3: Just noticed that the first parameter of the ReFFT method is a float[]. Let's try this:

double[] somerealData = new double[1000];
double[] someimgData = new double[1000];
//float[] zData placeholder since array comes from input param

object realData, imgData, zObj;
realData = somerealData;
imgData = someimgData;
zObj = zData;

ReFFT(zObj, ref realData, ref imgData);

double[] realDataArray = (double[])realData;
Console.WriteLine(realDataArray.Length);
realDataArray[0] = 1.0d;
Console.WriteLine(realDataArray[0]);
Josh E
  • 7,390
  • 2
  • 32
  • 44
  • I like the idea, but it's one I already tried (and tried again just now, to be extra sure). I still get the Type Mismatch error that's plaguing me. I noticed that when I put a breakpoint in the program, it tells me that "realData" and "imgData" have types of `object{double[]}` as opposed to pure `object`. Maybe that has something to do with it. – KChaloux Jul 08 '10 at 19:20
  • Hmmm. I tried out the code in my answer in LINQPad and it worked fine. Updating answer with a different approach – Josh E Jul 08 '10 at 19:26
  • Note that the FFT function comes from an external source: National Instruments Measurement Studio. The company uses it for almost everything, and it's given me a lot of trouble, working in subtly different ways from VB to C# with almost no documentation. I don't know if that might be causing my problem... – KChaloux Jul 08 '10 at 19:29
  • 3
    @KChaloux: it says the object's type is `object{double[]}` because all .NET types, including `double[]`, inherit from `object`. `object{double[]}` means that the variable's declared type is `object`, and its actual type is `double[]` – Thomas Levesque Jul 08 '10 at 19:35
  • well, in *theory*, it shouldn't have an effect on the code since it's simply modifying the arrays passed in via ref. I've tried messing with the arrays in the ReFFT func in my sample app, and it doesn't affect the outcome - it still works – Josh E Jul 08 '10 at 19:36
  • I've still got the same error as of Try 2. I went so far as to even commenting out ALL unrelated code in the function and copy/pasting your exact example in, to make sure it wasn't some unseen mistake on my part. My exact error: `{"Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))"}` Something I noticed when I stuck a breakpoint on there, though: The method is called in a Timer. The very first time it goes through, it doesn't seem to give me an error. I'm going to check something... – KChaloux Jul 08 '10 at 19:43
  • Do you know what the *test* object is used for in the function, i.e. what type does the function use it as? – Josh E Jul 08 '10 at 20:29
  • I wish I did, but I haven't been able to find out the actual meat of the function, beyond its basic signature. I don't imagine National Instruments would go around handing out their source code. – KChaloux Jul 08 '10 at 20:31
  • Just noticed that the first parameter is supposed to be an array of float... try using the same technique with that parameter that we have been previously trying and let's see what happens – Josh E Jul 08 '10 at 20:34
  • 1
    Unfortunately I already considered that and tried it. I think I'm about to give National Instruments a call and see if they can't figure this out... – KChaloux Jul 08 '10 at 20:40
0

What about just trying to send it an object, then check the type of what you get back. So something like this:

    private void FFT(float[] ZData, float[] FFTData)
    {
        object realData = new object();
        object imgData = new object();
    
        // (... Unrelated intermediate code ...)
    
        DSP.ReFFT(ZData, ref realData, ref imgData);
        
        // Find out what the type actual is (this will probably only work
        // if the values are assigned with the new data type)
        // but worth a shot:
        type t1 = typeof(realData);
        type t2 = typeof(imgData);
    
        // if t1 and t2 show the actual types, replace the
        // type above (new object() with the type here)
    
        // (... Unrelated intermediate code ...)
    }

Update: Just saw your last comment above. You'll probably want to create three seperate objects. Test1, Test2 and Test3 all as new object()'s.

From this post, it says for documentation to do the following:

Start >> All Programs >> National Instruments >> Measurement Studio 7.1 for VS .NET 2003 >> Measurement Studio Documentation

Then select "Measurement Studio" under the Filter pull down.

Now navigate the help tree to "NI Measurment Studio Help >> NI Measurement Studio .NET Class Library >> Reference >> National Instruments.Analysis.SpectralMeasurements >> Measurements Class >> Methods >> ReFFT??? Method.

Community
  • 1
  • 1
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
  • That's the bizarre thing that leads me to believe there's something terribly wrong with the function itself. Even if I send it all objects, it reports a Type Mismatch error. – KChaloux Jul 08 '10 at 20:29
  • No such luck in regards to creating 3 separate objects. Unfortunately I don't really know what it's doing with them, so if the error is on the inside of the function, it could be anything. – KChaloux Jul 08 '10 at 20:41
  • Hmm, yeah, have you tried using the 'out' keyword instead of 'ref', for the double[]'s? – SwDevMan81 Jul 08 '10 at 20:45
  • I actually hadn't, but apparently it results in a compile time error and tells me that I *must* use the `ref` keyword. – KChaloux Jul 08 '10 at 20:48
  • Wow, that is weird. I updated my post and put a link to some supposed documentation... maybe you can see if there is a function definition for it. – SwDevMan81 Jul 08 '10 at 20:51
0

You say that DSP is COM, and the odd errors you're getting suggests to me that the underlying problem is "marshalling" the parameters between .NET and COM. I am no expert on this, so this is more along the lines of a suggestion to investigate how one would encapsulate DSP in a COM-interop layer and calling it through that layer.

Here's a good starting point on MSDN: Introduction to COM Interop

Cyberherbalist
  • 12,061
  • 17
  • 83
  • 121
0

I never did figure out what was wrong with the function, so this answer might not help some people. Nevertheless, if you're using Measurement Studio in C# like I am and need to do a FFT, there was apparently a .NET class that includes it, and appears to work.

NationalInstruments.Analysis.Dsp.Transforms.FFT (and InverseFFT and a bunch of others). I'd still love to know what the deal with the other one was, though...

Thanks everyone for your suggestions. They were all logical ones that probably should have worked, but didn't for some unknown reason (likely relating to the inner workings of the function).

KChaloux
  • 3,918
  • 6
  • 37
  • 52