Передача объектов между C # и C

2

Мое приложение состоит из кода С# с неуправляемыми вызовами C dll. В моем коде С# у меня есть объект/класс, где его свойства являются как системными типами, такими как строка и int и другими объектами, которые я определил.

Я хотел бы передать этот комплексный объект (Graph.cs) в мой код C (dll), какую реализацию вы предложили бы здесь?

Я попытался переместить structs, но я не могу сделать это с чем-то другим, кроме string и int.

Спасибо.

код:

public Class Grpah {

    TupleCollection m_TupleCollection;
    int m_nGeneralIndex;       
    bool m_bPrintWRF;
    string m_sLink;  
}

public Class TupleCollection {

    IList<Tuple> _collection;

}     

public Class Tuple {

    Globals.TupleType m_ToppleType;        
    ArrayList m_Parameters;

}

public class TupleArgs {

    public string Value { get; set; }       
    public Globals.PAS PAS;
    public RefCollection RefCollection { get; set; }
    public int Time{ get; set; }      

}

public class RefCollection {

    public List<int> SynSet{ get; set; } 
    public Globals.PAS PAS;

}
  • 1
    Вы должны предоставить свой код, чтобы люди могли советовать.
  • 0
    Я добавил код, можно ли отправить объект Graph в C dll?
Показать ещё 1 комментарий
Теги:
dll
struct
unmanaged

3 ответа

6

Try:

Практическое руководство. Маршал-структуры с использованием PInvoke

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

Теперь вы почти наверняка используете Visual Studio, и, надеюсь, это VS2005 или новее. Это означает, что, хотя ваш существующий собственный код находится на C, у вас есть возможность вникать в небольшой С++. И не только это - у вас также есть С++/CLI.

Итак, я бы создал новую С++/CLI DLL и связал вашу библиотеку C с ней, чтобы она могла вызвать код C. Затем напишите тонкий слой перевода в библиотеке С++/CLI: он выведет истинные классы CLR (написанные с помощью ref class) и вызовет собственный C-код.

например. в заголовке C:

void do_something_with_foo_data(int a, int b, int c);

В С++/CLI:

public ref class FooWrapper
{
    static void DoSomethingWithFoo(Foo ^foo)
    {
        // pick apart the Foo class and pass the pieces on to the C function

        do_something_with_foo_data(foo->A, foo->B, foo->C);
    }
};

В С#:

public class Foo
{
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
}

...

var foo = new Foo { A = 1, B = 2, C = 3 };
FooWrapper.DoSomethingWithFoo(foo);
  • 0
    Спасибо, в этом примере они используют только простой тип данных, такой как int, который я могу обработать, как насчет типа данных C # List? или ListArray.
  • 0
    Вы не можете обрабатывать управляемые структуры из неуправляемого кода. Вам необходимо преобразовать эти структуры в неуправляемые структуры и передать их. Этот ответ является наиболее верным, который я видел здесь.
Показать ещё 3 комментария
2

Когда я это сделал, я использовал Marshal. Это было со стандартом C для собственного кода. Я не хотел преобразовывать свой C-код в "управляемый С++" или как он его называет: -)

Жесткая и утомительная часть состоит в том, что вы должны вручную маршевать структуру данных во что-то, что напрямую связано с принимающей функцией C. В моем случае мне приходилось создавать отдельные структуры для каждого документа, несущего класс С#, который я хотел отправить. В сущности, вы должны преобразовать свою красивую иерархию объектов С# в более базовую форму, состоящую из структур, которые затем маршалируете в блок памяти, который затем используется в качестве аргумента в вашем родном вызове.

Вы должны использовать метод Marshal.AllocHGlobal для выделения памяти и Marshal.StructureToPtr для копирования вашей структуры С# в эту память, а затем Marshal.FreeHGlobal, чтобы освободить ее.

Как только у вас есть IntPtr (от StructureToPtr), вы сможете просто вызвать свою C-dll с указанным указателем в качестве аргумента. Обратите внимание, что структура, которую вы отправляете на свою C-функцию, должна иметь тот же макет, что и родная C-структура, или вы получите очень нечетные результаты.

Возвращаемые данные - почти то же самое, но вместо этого вы используете противоположные функции (PtrToStructure и т.д.).

В любом случае это основное.

  • 0
    +1 Не уверен, что мне на самом деле нравится это звучание на практике, но тем не менее это интересно.
  • 0
    Хех, спасибо Но если вы не хотите портировать существующий нативный код или написать эту обёртку C ++, насколько я знаю, это единственный путь вперед.
Показать ещё 1 комментарий
0

Ваша модель выглядит довольно сложной и неполной: Tuple.m_parameters - это ArrayList, поэтому он может содержать почти что угодно, а тип Globals.PAS здесь не определен.

Возможно, вам стоит подумать о другой стратегии: в своей DLL создайте небольшую модель, которая содержит все, что вам нужно в вашем C-коде, и сделайте ее максимально простой (но не простой!).

Затем изучите все, что вам нужно, чтобы вывести эту модель C из управляемого кода и заполнить модель из вашего класса Graph.cs. Предпочтительно, Graph.cs не должен нести ответственность за это, ваш код маршаллинга должен быть.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню