2011-01-17 1 views
1

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

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

Я пытаюсь написать новое приложение win32 C# .NET, используя этот старый контроль OCX. Я использовал следующую команду:

AxImp spectrograph.ocx 

для создания AxSPECTROGRAPHLib.dll. Я могу импортировать элемент управления (через вновь созданный .dll) в свою IDE (SharpDevelop), где я могу добавить его в форму, как и любой другой элемент управления. До сих пор так хорошо, пока я пытаюсь передать поплавок [] к методу 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 

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

ответ

0

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

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

Ему нужно получить доступ не только к первому элементу, но, к сожалению, я не думаю, что это сработает. – Tim

+0

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

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

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

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

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

0

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

Обратите внимание, что я не пробовал обходной путь, так как я получил доступ к источнику моего элемента управления ocx, я просто изменяю параметр указателя на тип SAFEARRAY. И сделать это HERE - подробный пример.

Я также попытался изменить IL классов InterOP и перекомпилировать, как описано HERE, но этот метод не работает для меня. Возможно, я ошибаюсь.

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

 Смежные вопросы

  • Нет связанных вопросов^_^