Выделение элементов кода в IntPtr в C # - PullRequest
1 голос
/ 19 августа 2009

Я пишу надстройку Visual Studio, и мне необходимо преобразовать управляемый объект CodeElements в его необработанную форму. Мне просто нужен указатель в памяти, так как я могу привести его и обработать как CodeElement на неуправляемой стороне.

    [DllImport("CodeMethodsToString.dll")]
    private static extern BSTR* CodeMethodsToString(void* functionObject);

    public static void CodeMethodsToXML(XmlElement parent, CodeElements elements)
    {
        //Call CodeMethodsToString: how do I marshall CodeElements to an IntPtr?
        //set XmlElement in here
    }

Я знаю, как обращаться с XML, и у меня есть рабочая версия этого на C #. Я создал неуправляемую DLL, потому что вызов всех переменных-членов на самом низком уровне рекурсии убивал скорость программы. Мне просто нужно знать, как использовать System.Runtime.Interop.Marshal для преобразования объекта CodeElements в указатель на объект COM в памяти.

Спасибо.

Ответы [ 4 ]

3 голосов
/ 27 августа 2009

Похоже, Джонатан был рядом. Вот как я это сделаю:

[DllImport("CodeMethodsToString.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string CodeMethodsToString(IntPtr functionObject);

public static void CodeMethodsToXML(XmlElement parent, CodeElements elements)
{
   GCHandle pin;
   try
   {
      pin = GcHandle.Alloc(elements, GCHandleType.Pinned);
      string methods = CodeMethodsToString(pin.AddrOfPinnedObject());
    }
    finally
    {
       pin.Free();
    }
}
1 голос
/ 09 января 2012

При желании вы можете посмотреть пример в конце статьи: GCHandle MSDN

1 голос
/ 24 августа 2009

Как только вы видите звезду или амперсанд, вам следует начать с преобразования ее в ref (безопасная версия указателя). У меня были ссылочные типы, которые волшебным образом начали работать, когда я использовал ключевое слово ref в прошлом (что весьма противоречиво - но я думаю, что это одна из тех вещей взаимодействия):

[DllImport("example.dll")]
private static extern void DoStuff(ref CodeElements codeElements);

Вы также можете попробовать:

[DllImport("example.dll")]
private static extern void DoStuff([In, Out] ref CodeElements codeElements);

Или одна из комбинаций этих атрибутов.

Одна вещь, которую вы, возможно, захотите попробовать, - это использовать MFC (я думаю, это было давно с C ++) для создания библиотеки COM. Не используйте собственный вызов, экспортируйте объект как библиотеку типов и добавьте его в качестве ссылки в Visual Studio (да, это так просто). Таким образом, вы получите что-то вроде:

myCoolClass.DoStuff(codeElements);

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

GCHandle handle = new GCHandle();
try
{
  handle = GCHandle.Alloc(fooz, GCHandleType.Pinned);
  // Use fooz.
}
finally
{
  if (handle.IsAllocated)
    handle.Free();
}
1 голос
/ 20 августа 2009

Является ли CodeElements интерфейсом ComVisible и имеет GuidAttribute?

Тогда C # выполнит маршалинг COM-объектов за вас, и вы можете просто использовать CodeElements в качестве типа аргумента:

[DllImport("example.dll")]
private static extern void DoStuff(CodeElements codeElements);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...