передача массива с плавающей запятой из c # в ocx, написанного на vc ++ 6 - PullRequest
1 голос
/ 18 января 2011

У меня есть старый ocx (spectrograph.ocx), написанный на VC ++ 6.Он содержит метод AppendDataX (), который определен следующим образом:

afx_msg void AppendDataX(float FAR* data, long n, float xpos);

Я пытаюсь написать новое Win32-приложение на C # .NET с использованием этого старого элемента управления ocx.Я использовал следующую команду,

AxImp spectrograph.ocx

, чтобы создать AxSPECTROGRAPHLib.dll.Я могу импортировать элемент управления (через вновь созданный .dll) в свою среду IDE (SharpDevelop), где я могу добавить его в форму, как и любой другой элемент управления.Пока все хорошо, пока я не попытаюсь передать float [] в метод ocx AppendDataX ():

        FileStream tw = new FileStream("XX-YY-ZZZZ.2011.01.10.15.52.00.spec", FileMode.Open);
        BinaryReader br = new BinaryReader(tw);
        int pixelCnt = br.ReadInt32();
        float[] wavelength = new float[pixelCnt];
        for (int i=0; i<pixelCnt; i++)
            wavelength[i] = br.ReadSingle();

        bool eof = false;
        float temp;
        float[] spectrum = new float[pixelCnt];
        while(!eof)
        {
            try
            {
                temp = br.ReadSingle();
                for (int i=0; i<pixelCnt; i++)
                    spectrum[i] = br.ReadSingle();

                spec.AppendDataX(spectrum, pixelCnt, temp);
            }
            catch(EndOfStreamException)
            {
                eof = true;
            }
        }
        tw.Close();

Это приводит к следующей ошибке во время компиляции:

Argument '1': cannot convert from 'float[]' to 'ref float' (CS1503)

У меня естьиспользовал дизассемблер MSIL для генерации AxSPECTROGRAPHLib.il, и я получил это:

  .method public hidebysig newslot virtual 
      instance void  AppendDataX(float32& data,
                                 int32 n,
                                 float32 xPos) cil managed
{
// Code size       35 (0x23)
.maxstack  8
IL_0000:  ldarg.0
IL_0001:  ldfld      class [SPECTROGRAPHLib]SPECTROGRAPHLib._DSpectrograph AxSPECTROGRAPHLib.AxSpectrograph::ocx
IL_0006:  brtrue.s   IL_0014

IL_0008:  ldstr      "AppendDataX"
IL_000d:  ldc.i4.0
IL_000e:  newobj     instance void [System.Windows.Forms]System.Windows.Forms.AxHost/InvalidActiveXStateException::.ctor(string,
                                                                                                                         valuetype [System.Windows.Forms]System.Windows.Forms.AxHost/ActiveXInvokeKind)
IL_0013:  throw

IL_0014:  ldarg.0
IL_0015:  ldfld      class [SPECTROGRAPHLib]SPECTROGRAPHLib._DSpectrograph AxSPECTROGRAPHLib.AxSpectrograph::ocx
IL_001a:  ldarg.1
IL_001b:  ldarg.2
IL_001c:  ldarg.3
IL_001d:  callvirt   instance void [SPECTROGRAPHLib]SPECTROGRAPHLib._DSpectrograph::AppendDataX(float32&,
                                                                                                int32,
                                                                                                float32)
IL_0022:  ret
} // end of method AxSpectrograph::AppendDataX

Я искал и искал простой пример, показывающий сортировку из float [] из c # в ocx vc6 ++, но у меня нетпока не нашел пример, который работает для меня.Может ли кто-нибудь помочь привести меня в правильном направлении ... Я чувствую, что на правильном пути, и это действительно не должно быть так сложно сделать, но я чувствую, что застрял после просмотра этого в течение нескольких дней.

Ответы [ 3 ]

1 голос
/ 18 января 2011
afx_msg void AppendDataX(float FAR* data, long n, float xpos);

Это проблема, это не подпись функции, совместимой с Automation.Массивы должны передаваться как SafeArray, а функция должна возвращать HRESULT.В настоящее время импортер библиотек типов не может догадаться, что первый аргумент является массивом, он также может быть указателем на одно значение с плавающей точкой.Это то, о чем он догадывался, ref float.

Если вы не можете изменить собственный код, то вы можете технически отредактировать сгенерированную библиотеку взаимодействия и изменить подпись, используя float [].Ваша разборка это очень странно, кстати, никогда не видел этого раньше.CLR обычно генерирует COM-заглушки динамически из объявления функции в библиотеке взаимодействия.Не знаю, как вы получили то, что вы опубликовали.

Технически возможно получить экспорт модулей в библиотеку типов.Это, однако, не OCX.Однако он объясняет неавтоматизированную сигнатуру и заглушку IL.В этом случае может быть проще создать небольшую оболочку класса C ++ / CLI ref, которая напрямую использует экспортируемую функцию, а не библиотеку типов.Преобразование массива в число с плавающей точкой * легко с pin_ptr <>.

0 голосов
/ 01 июля 2014

Я недавно столкнулся с этой проблемой.И я нашел решение ЗДЕСЬ .Создание вспомогательной dll для вызова фактической функции с типом SAFEARRAY.

Обратите внимание, что я не пробовал обходной путь, так как я получил доступ к источнику моего элемента управления ocx, я просто изменил параметр указателя на тип SAFEARRAY,И для этого ЗДЕСЬ является подробным примером.

Я также пытался изменить IL классов InterOP и перекомпилировать, как описано ЗДЕСЬ , но этот метод не работаетдля меня.Может быть, я делаю это неправильно.

Я сходил с ума от этой проблемы, как и вы, поэтому я надеюсь, что вы можете выйти из этого.

0 голосов
/ 18 января 2011

Хорошо, если элемент управления хочет буквально адрес первого элемента, вы всегда можете закрепить его и вернуть адрес:

var handle=GCHandle.Alloc( spectrum, GCHandleType.Pinned );
unsafe
{
    float *val=(float *)handle.AddrOfPinnedObject();
    // here's the val to send to your object
}
handle.Free();
...