Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Как получить параметр


Автор: DimaKGZ 4.9.2005, 19:47
Здравствуйте!

У меня такая проблема

Есть некая библиотека на с

Код


TEST_API int fnTest(int *t)
{
  *t = 10;
  return 42;
}



на С# вызываю процедуру так

Код


[DllImport("test")]
private static extern int fnTest(out int a);
[STAThread]
static void Main(string[] args)
{
  int a = 0;
  fnTest(out a);
}


теперь мне надо все это написать на J#

Код

/**@attribute DllImport("test")*/
private static native int fnTest(Integer a);
    
/** @attribute System.STAThread() */
public static void main(String[] args)
{        
  Integer a = new Integer(0);
  fnTest(a);    
}

и у меня появляется сообщение об ошибке

An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in ConsoleApplication1.exe

Additional information: Can not marshal parameter #1: The type definition of this type has no layout information.

нет на j# волшебного OUT smile

что делать??

Автор: mr.DUDA 4.9.2005, 20:49
Дело в том, что J# - суть враппер над Java. Поэтому все возможности языка соответствуют возможностям Java. Если там нет поддержки указателей (ссылок), то нельзя будет написать метод, принимающий аргумент-указатель. И наоборот. Советую задать вопрос в разделе по Java: "Возможно ли использование Си-указателей в JAVA ?", с подробным описанием проблемы, только без ссылок на .NET smile.

Автор: DimaKGZ 5.9.2005, 05:37
К сожалению JAVA позволяет передавать параметры только по значению smile

Если нужно получить несколько значений то приходится извращаться и возвращать или в массиве или в классе - обертке.

Но тут .NET ... думал может с помощью хитро приложенного маршалинга можно это реализовать..
поэтому вопрос и был в .net раздел.

Си библиотеку переписывать нежелательно.. А заставить работать с J# нужно

Автор: Domestic Cat 5.9.2005, 06:12
Я J# не знаю, но разве не должно работать что-то вроде
Код

public static void main(string[] args)
{
  int a = 0;
  a = fnTest(a);
}

?

Автор: DimaKGZ 5.9.2005, 06:25
да таким образом можно ПЕРЕДАТЬ значение по ссылке

Код

TEST_API int fnTest(int *t)
{
  print(t) // распечатает 10
  return 42;
}



Код

public static void main(string[] args)
{
  int a = 10;
  a = fnTest(a);
}


а вот вернуть знаечение не получается.. smile

Автор: mr.DUDA 5.9.2005, 06:59
Раз используется .NET, можно обойти проблему следующим образом. Написать на C# класс-обёртку:

Код
using System;
using System.Runtime.InteropServices;

namespace ClassLibrary1
{
    public class MyWrapper
    {
        [DllImport("Win32Dll")]
        private static extern int fnTest(out int a);

        public static int[] FnTest()
        {
            int [] result = {0,0};
            result[0] = fnTest(out result[1]);
            return result;
        }
    }
}


Скомпилировав, получаем assembly, которую можно по reference включить в проект на J#. Дальше всё понятно:

Код
public static void main(String[] args)
{
    int[] result = ClassLibrary1.MyWrapper.FnTest();
}


Вот тестовый проект, проверял под отладкой - работает:

Автор: DimaKGZ 5.9.2005, 07:13
Большое спасибо smile

Первоначально проект так и выглядел smile smile

Была обертка на с#..

Заказчик захотел избавиться от обертки и портировать код с# на J ..
Уговоры и убеждения не помогли.. Хозяин барин..

буду дальше копаться..

Спасибо

Автор: mr.DUDA 5.9.2005, 09:18
Так портируй весь код на J#, кроме обёртки для вызова native методов. Заказчику наверное важней получить хоть какой-то порт под Java, чем кол-во получаемых DLL.

Автор: DimaKGZ 6.9.2005, 09:41
smile

Есть просто большой проект на J#.

он "общался" с библиотеками на с++ через обертки на C# .

и вот товарищ уважаемый заказчик захотел избавиться от оберток (этот вопрос к нему - зачем?).

Вот результаты моих изысканий - на J# нельзя получить параметры (см. первый пост). Кто научит как это можно сделать

перед тем "сниму шляпу"... мне это не удалось smile

переписал библиотеки сишные заточив их вызовы под java


Автор: Дрон 10.9.2005, 23:10
Цитата(DimaKGZ @ 6.9.2005, 10:41)
переписал библиотеки сишные заточив их вызовы под java

Т.е. тема уже не актуальна?

Если же всё-таки интересно, то вот то, что я накопал:
Код

import System.*;
import System.Runtime.InteropServices.*;

public class Class1
{

/**@attribute DllImport("test")*/
private static native int fnTest(/**@attribute OutAttribute()*/Integer a);

...
}


Проверить я не могу, ибо в J# не силён. Но оно, как минимум, компилируется smile

Автор: Дрон 10.9.2005, 23:40
Хмм... Проверил. Тот же эксепшен.
Зато нашёл другое решение. Работает на ура.
Код

import System.*;
import System.Runtime.InteropServices.*;

public class Class1
{
   /**@attribute DllImport("Win32Dll")*/
   private static native int fnTest(IntPtr addr);

   public static void main(String[] args)
   {
      IntPtr addr = Marshal.AllocHGlobal(4);
      fnTest(addr);
      Integer val = new Integer(Marshal.ReadInt32(addr));
      Marshal.FreeHGlobal(addr);

      
      Console.WriteLine("{0}",val);
   }
}

Автор: DimaKGZ 20.9.2005, 12:22
Во истину - кто ищет тот найдет..

выражаю своё уважение тов. Дрону..

действительно работает..

private static native int fnTest(/**@attribute OutAttribute()*/Integer a); - такое видел у Майкрософта в примерах.. только там

все относилось к 2005 студии.. у меня в 2003 не работало.. может это баг мелких что атрибут не работает... быть может

новый фреймворк уже умеет это делать smile .. кто знает...

спасибо.. находка интересная..

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)