Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Получение указателя на структуру из unmanaged code, Необходимо занести значения в структуру  
V
    Опции темы
Ky7m
Дата 23.10.2010, 11:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 8.4.2008

Репутация: 1
Всего: 2



Возникла проблема, описанная в этой теме [LINK], так как с места тема не сдвинулась, решаю своими рассуждениями и предположениями. Нужен опытный совет или решение. 
Основная проблема, в том что в DLL есть структура, описание которой я знаю. Необходимо получить её адрес и заполнить значениями все поля. 
Поэтому возникает вопрос, что если получить адрес на начало структуры и потом скопировать уже проинициализированную данными структуру, созданную в программе, в эту область памяти? 
Какие способы получения адреса на точку входа? Я экспериментировал и следующий код
Код

[DllImport("PhGain_win32.dll", EntryPoint = "PhGain_Y", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern void PhGain_Y(); // PhGain_Y - структура

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

P.S. Извините, скорей всего это похоже на повторное создание темы, но мне кажется, что созданная исходная тема в "ветке Новичков" результатов не принесет, поэтому, если я прав, то просьба модератору перенести соответсвующую тему [LINK] в эту ветку.

С уважением Игорь aka Ky7m

PM MAIL ICQ   Вверх
sCreator
Дата 23.10.2010, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 84
Регистрация: 20.8.2009
Где: Московская област ь

Репутация: 1
Всего: 5



Для начала надо правильно записать определение структуры на C#.

Далее, если ничего не найдете по передаче адреса структур ( я пока не встречал - встречал только импорт функций ),
Напишите на С++ dll посредник - которая будет реэкспортировать функции и отдавать адреса структур с помощью функций типа
extern ExternalInputs_PhGain* GetInputsGain(void);

Это сообщение отредактировал(а) sCreator - 23.10.2010, 16:36
PM   Вверх
Ky7m
Дата 23.10.2010, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 8.4.2008

Репутация: 1
Всего: 2



Цитата(sCreator @ 23.10.2010,  16:35)
Для начала надо правильно записать определение структуры на C#.

Далее, если ничего не найдете по передаче адреса структур ( я пока не встречал - встречал только импорт функций ),
Напишите на С++ dll посредник - которая будет реэкспортировать функции и отдавать адреса структур с помощью функций типа
extern ExternalInputs_PhGain* GetInputsGain(void);

Структуру записал, думаю проблем не будет с этим. Вот не хотелось еще одну библиотеку заводить. Просто не могу поверить, что C# не позволит мне получить адрес на структуру. Еще есть вариант небеопсного кода, но опять не хотелось, потому что теряется красота C#.
С уважением Игорь aka Ky7m

PM MAIL ICQ   Вверх
sCreator
Дата 24.10.2010, 11:43 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 84
Регистрация: 20.8.2009
Где: Московская област ь

Репутация: 1
Всего: 5



Я тоже не мог поверить но похоже это факт.

Сделал такой вариант библиотеку С++ с одной функцией которая может выдавать адреса символов из других библиотек ( типа чтото универсальное )
simbolloader.h :
Код

#ifdef SIMBOLLOADER_EXPORTS
#define SIMBOLLOADER_API __declspec(dllexport)
#else
#define SIMBOLLOADER_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif
SIMBOLLOADER_API INT_PTR loadsimbol(
    __in LPCSTR lpLibFileName,
    __in LPCSTR lpProcName
    );
#ifdef __cplusplus
}
#endif

simbolloader.cpp :
Код

// simbolloader.cpp: определяет экспортированные функции для приложения DLL.
//

#include "stdafx.h"
#include "simbolloader.h"


SIMBOLLOADER_API INT_PTR loadsimbol(
    __in LPCSTR lpLibFileName,
    __in LPCSTR lpProcName
    )
{
    HMODULE hinstLib = LoadLibraryA(lpLibFileName); // load to memory
    if (hinstLib == NULL) 
        return NULL;

    INT_PTR procAddress = (INT_PTR)GetProcAddress(hinstLib, lpProcName);
    FreeLibrary(hinstLib);
    return procAddress;

}


Тест на С#
Program.cs :
Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace stucturer
{
    class Program
    {
        static void Main(string[] args)
        {
            IntPtr addr;
            //addr = Marshal.GetFunctionPointerForDelegate(new myDeleg(Ex.myIn));
            //addr = Ex.getPhGain();
            addr = SimbolLoader.LoadSimbol("testlib.dll", "myTestStr");
            Console.WriteLine(Ex.fntestlib(20));

            ExternalInputs_PhGain gan = (ExternalInputs_PhGain)Marshal.PtrToStructure(addr, typeof(ExternalInputs_PhGain));
            Console.WriteLine(" ----- {0}", gan.In0);
            Console.WriteLine(Ex.fntestlib(21));
            Console.WriteLine(Ex.fntestlib(22));
            gan = (ExternalInputs_PhGain)Marshal.PtrToStructure(addr, typeof(ExternalInputs_PhGain));
            Console.WriteLine(" ----- {0}", gan.In0);
            Console.ReadKey();
        }
    }
    
     delegate void myDeleg();

    class Ex
    {
        [DllImport("testlib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int fntestlib(int p1);

        [DllImport("testlib.dll", EntryPoint = "myTestStr")]
        public static extern void myIn();

        [DllImport("testlib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr getPhGain();
    }


    [StructLayout(LayoutKind.Sequential)]
    struct ExternalInputs_PhGain
    {
        public int In0;
        public int In1;
    }
}

SimbolLoader.cs :
Код

using System;
using System.Runtime.InteropServices;

namespace stucturer
{
    public static class SimbolLoader
    {
        [DllImport("simbolloader.dll", EntryPoint = "loadsimbol", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr LoadSimbol(string lpLibFileName, string lpProcName);
    }
}

Ну и тестовая dll
testlib.h :
Код

// Приведенный ниже блок ifdef - это стандартный метод создания макросов, упрощающий процедуру 
// экспорта из библиотек DLL. Все файлы данной DLL скомпилированы с использованием символа TESTLIB_EXPORTS,
// в командной строке. Этот символ не должен быть определен в каком-либо проекте
// использующем данную DLL. Благодаря этому любой другой проект, чьи исходные файлы включают данный файл, видит 
// функции TESTLIB_API как импортированные из DLL, тогда как данная DLL видит символы,
// определяемые данным макросом, как экспортированные.
#ifdef TESTLIB_EXPORTS
#define TESTLIB_API __declspec(dllexport)
#else
#define TESTLIB_API __declspec(dllimport)
#endif

typedef struct {
  int In0;
  int In1;
} ExternalInputs_PhGain;

#ifdef __cplusplus
extern "C" {
#endif

TESTLIB_API ExternalInputs_PhGain myTestStr;

TESTLIB_API int fntestlib(int p1);

TESTLIB_API ExternalInputs_PhGain* getPhGain(void);

#ifdef __cplusplus
}
#endif

testlib.cpp : 
Код

// testlib.cpp: определяет экспортированные функции для приложения DLL.
//

#include "stdafx.h"
#include "testlib.h"

// Пример экспортированной функции.
TESTLIB_API int fntestlib(int p1)
{
    int p = myTestStr.In0;
    myTestStr.In0=p1;
    return p;
}

TESTLIB_API ExternalInputs_PhGain* getPhGain(void){
    return &myTestStr;
}

В С++ я неочень - в основном читаю.

PM   Вверх
Ky7m
Дата 24.10.2010, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 8.4.2008

Репутация: 1
Всего: 2



Спасибо за пример и благодарю за помощь, интересно копнуть в этом направлении. Я пока пошел рутинным путем и сделал  обвертку (теперь еще плюс одна dll), и пока она работает оставлю так как есть, а для себя хочу разобраться с этой проблемой. Модифицировать приведенный пример для моей задачи. 
Но хочется найти что-то проще и красивей, но смотрю, что с этим никто не встречался.
PM MAIL ICQ   Вверх
sCreator
Дата 24.10.2010, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 84
Регистрация: 20.8.2009
Где: Московская област ь

Репутация: 1
Всего: 5



Модифицировать просто.
simbolloader.h (.cpp) - это все что я написал в С++ проекте Win32 - библиотека dll
(может что надо дописать, а то пришлось  применять CallingConvention = CallingConvention.Cdecl)
SimbolLoader.cs - ее описание в C#.

IntPtr - типа указателя неуправляемой памяти

Маршалинг взаимодействия
Маршалинг данных при вызове неуправляемого кода
Marshal.PtrToStructureMarshal.PtrToStructure только копирует данные в управляемый код - есть обратный мотод.

Перешел на активную работу в C# с полгода, но уже есть несколько моментов ограниченности. Т.е. вроде универсальный и только собирай из кирпичиков - но не все включено.

Это сообщение отредактировал(а) sCreator - 24.10.2010, 17:15
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0436 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.