Гость
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Опять С# pinvoke Cpp dll / 19 сообщений из 19, страница 1 из 1
02.02.2017, 14:25
    #39397261
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Добрый день, коллеги!

Как всегда нужна ваша помощь.

C++
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
#include "C:\Users\vvf6426\Documents\testDLL\header.h"
#include "C:\Users\vvf6426\Documents\testDLL\body.cpp"
#include <comutil.h>
#include <queue>

using namespace std;


extern "C" __declspec(dllexport) double sumTwo(double var_x, double var_y)
{
	myClass MC(var_x, var_y);
	return MC.sumX_Y();
}

extern "C" _declspec(dllexport) BSTR getNskv()
{
    return ::SysAllocString(L"Greetings from the native world!");
}

typedef struct
{
	int   id;
	char* name;
	int   age;
	int   sex;
} PERSON;

std::queue<PERSON> result;

int i;
int main() {
	while ( i<= 3 ) {
		PERSON person;
		person.id = i;
		person.age = i*i;
		person.sex = 1;
		person.name = "Ivan";
		result.push(person);
		++i;
	}
}



C#
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
namespace MvcCppDLL.Models
{
    public class GetDataCppDLL
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int X { get; set; }
        public int Y { get; set; }
        public string b { get; set; }

        [DllImport(@"C:\Musor\CppClassDll\Release\CppClassDll.dll", CallingConvention = CallingConvention.Cdecl)] // устанавливаем название используемой библиотеки
        public static extern double sumTwo(double var_x, double var_y);
        

        [DllImport(@"C:\Musor\CppClassDll\Release\CppClassDll.dll", CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.BStr)]
        private static extern string getNskv();

        public double getSumm()
        {
            double summ = 0;
            summ = sumTwo(X,Y);
            return summ;
        }

        public string getByte()
        {
            b = getNskv();
            return b;
        }
    }
}



Числовое и строковое значение получил, а вот со стеком структуры застрял, чет никак не соображу.
Помогите пожалуйста вытащить result из DLL.
Спасибо большое!
...
Рейтинг: 0 / 0
02.02.2017, 15:05
    #39397315
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
vadipokстеком структуры
что это?
...
Рейтинг: 0 / 0
02.02.2017, 15:46
    #39397360
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Изопропилvadipokстеком структуры
что это?

Не придирайтесь плиз к словам, я в терминологии С++ не силен.
Как передать result c тремя struct внутри? Основной вопрос такой.
...
Рейтинг: 0 / 0
02.02.2017, 16:32
    #39397419
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Изопропилvadipokстеком структуры
что это?std::queue<PERSON> result;
это вроде очередь
...
Рейтинг: 0 / 0
02.02.2017, 16:42
    #39397431
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Roman MejtesИзопропилпропущено...

что это?std::queue<PERSON> result;
это вроде очередь

Парни, да без разницы как она там называется.
Можете предложить что-то другое для решения этой задачи.
Главное получить примерно такой список в выходе С#.
Я это от балды набрал, чтобы тому кто будет помогать, меньше писать.
Горю, очень нужна помощь.
...
Рейтинг: 0 / 0
02.02.2017, 20:05
    #39397585
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
vadipok,

если достаточно копии - получить как массив структур,
если из c# с очередью нужно работать - COM объект реализовать, либо набор функций(что не очень удачным будет)
...
Рейтинг: 0 / 0
03.02.2017, 07:34
    #39397743
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Изопропилvadipok,

если достаточно копии - получить как массив структур,
если из c# с очередью нужно работать - COM объект реализовать, либо набор функций(что не очень удачным будет)

Добрый день, спасибо за совет.
Скиньте плиз пример, если это возможно.
Или ссылку на туториал.
...
Рейтинг: 0 / 0
03.02.2017, 09:52
    #39397807
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
С просто struct то же разобрался, остается сделать из него array queue или еще что ни будь.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
struct Name
{	
	char FirstName[100];
	char LastName[100];
};

extern "C" __declspec(dllexport) void __cdecl GetName(struct Name *name)
{
	strncpy_s(name->FirstName, "FirstName", sizeof(name->FirstName));
	strncpy_s(name->LastName, "LastName", sizeof(name->LastName));
}



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
        [StructLayout(LayoutKind.Sequential)]
        public struct Name
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
            public string FirstName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
            public string LastName;
        };

        [DllImport(@"C:\Musor\CppClassDll\Release\CppClassDll.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void GetName(ref Name name);

        public string getByte()
        {
            b = getNskv();
            var name = new Name();
            GetName(ref name);
            return b;
        }
...
Рейтинг: 0 / 0
03.02.2017, 09:53
    #39397810
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Интересное конечно решение, тут получается мы передаем переменную, она там присваивается и возвращается обратно.
Я не думал что они так плотно могут работать между собой.
...
Рейтинг: 0 / 0
03.02.2017, 10:07
    #39397830
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
vadipokС просто struct то же разобрался, остается сделать из него array queue или еще что ни будь.
Код: c#
1.
Queue<Name> result;


полный аналог для
Код: plaintext
1.
std::queue<PERSON> result;
...
Рейтинг: 0 / 0
03.02.2017, 10:19
    #39397843
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Dima TvadipokС просто struct то же разобрался, остается сделать из него array queue или еще что ни будь.
Код: c#
1.
Queue<Name> result;


полный аналог для
Код: plaintext
1.
std::queue<PERSON> result;



Дима, а нельзя полный пример.
То что вы написали, я уже знал до этого.
И уже догадывался что вместо ref Name name нужно передать result как ни будь, и как ни будь его там присвоить. )))
А вообще спасибо.
Хотя, пока не надо, попробую сам сперва разобраться.
...
Рейтинг: 0 / 0
03.02.2017, 11:16
    #39397928
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
vadipok,

с возвратом массива и C-строками :
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    struct PERSON
    {
        public int id;
        [MarshalAs(UnmanagedType.LPStr)]
        public string name;
        public int age;
        public int sex;
    }

 [DllImport(@"C:\VC\Test05\Debug\cdll.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int getA([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref   PERSON[] p, ref int c);



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
struct PERSON1
{
	int   id;
	char* name;
	int   age;
	int   sex;
};


extern "C" __declspec(dllexport) void  WINAPI getA(PERSON1 ** p, int *c)
{
	if ( *p) {
		for (int i = 0; i < *c; i++) {
			::CoTaskMemFree((*p)[i].name);
			(*p)[i].name = nullptr;
		}
		::CoTaskMemFree(*p);
		*p = nullptr;
	}
	
	size_t sz = 10;
	PERSON1 *pt = (PERSON1*)CoTaskMemAlloc(sz*sizeof PERSON1);
	memset(pt, 0, sz * sizeof PERSON1);
	 
	 pt->age = 800;
	 std::string n = "asdf";
	 pt->name = (char*)::CoTaskMemAlloc(n.length()+1);
	 memcpy(pt->name,  n.c_str(), n.length()+1);

	 *p = pt;
	 *c = sz;
}
...
Рейтинг: 0 / 0
03.02.2017, 12:32
    #39398040
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
ну и пример COM интеропа
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct PERSON
    {
        public int id;
        [MarshalAs(UnmanagedType.LPStr)]
        public string name;
        public int age;
        public int sex;
    }
;
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("8EE3561E-0EE1-441E-9C37-21789DA963AF")] 
    interface IMyQueue
    {
        void push(ref  PERSON p);
        void pop();
        PERSON front();
        PERSON back();
        int size();
    }
 [DllImport(@"C:\VC\Test05\Debug\cdll.dll", CallingConvention = CallingConvention.StdCall)]        
        private static extern IMyQueue getO();
....

IMyQueue q = getO();
            int cc = 0;
            PERSON person = new PERSON() { age = 888, name = "AS", id = 300, sex = 2 };
            q.push(ref person);
            person = new PERSON() { age = 11, name = "яп", id = 1, sex = 1 };
            q.push(ref person);
            cc = q.size();
            person = q.front();
            person = q.back();
            q.pop();
            Marshal.ReleaseComObject(q);


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
struct PERSON
{
	int   id;
	char* name;
	int   age;
	int   sex;
	PERSON() :name(nullptr), id(0), age(0), sex(0) {};
	PERSON(const PERSON &s) : name(nullptr), id(s.id), age(s.age), sex(s.sex) {
		if (s.name) {
			size_t l = strlen(s.name) + 1;
			this->name = (char*)::CoTaskMemAlloc(l);
			memcpy(this->name, s.name, l);
		}
	}
	PERSON& operator=(PERSON s) {
		id = s.id;
		age = s.age;
		sex = s.sex;
		if (s.name) {
			size_t l = strlen(s.name) + 1;
			this->name = (char*)::CoTaskMemAlloc(l);
			memcpy(this->name, s.name, l);
		}
		else {
			s.name = nullptr;
		}
		return *this;
	}
	~PERSON() {
		::CoTaskMemFree(name);
		name = nullptr;
	};
};




// {8EE3561E-0EE1-441E-9C37-21789DA963AF}
static const GUID IID_IMyQueue =
{ 0x8ee3561e, 0xee1, 0x441e,{ 0x9c, 0x37, 0x21, 0x78, 0x9d, 0xa9, 0x63, 0xaf } };
class IMyQueue :public IUnknown {
public:
	virtual HRESULT STDMETHODCALLTYPE push(const PERSON&) = 0;
	virtual HRESULT STDMETHODCALLTYPE pop() = 0;
	virtual HRESULT STDMETHODCALLTYPE front(PERSON&) = 0;
	virtual HRESULT STDMETHODCALLTYPE back(PERSON&) = 0;
	virtual HRESULT STDMETHODCALLTYPE size(int&) = 0;
};


class MyQueue :public IMyQueue {
	ULONG  refc;
	std::queue<PERSON> q;
public:
	MyQueue();
	virtual ~MyQueue();
	virtual STDMETHODIMP push(const PERSON &);
	virtual STDMETHODIMP pop();
	virtual STDMETHODIMP front(PERSON &);
	virtual STDMETHODIMP back(PERSON &);
	virtual STDMETHODIMP size(int &);
	virtual STDMETHODIMP QueryInterface(REFIID, void **);
	virtual ULONG STDMETHODCALLTYPE AddRef(void);
	virtual ULONG STDMETHODCALLTYPE Release(void);
};

MyQueue::MyQueue() :refc(1) {
};

MyQueue::~MyQueue() {
};
STDMETHODIMP MyQueue::push(const PERSON & t) {
	q.push(t);
	return S_OK;
};
STDMETHODIMP MyQueue::pop() {
	q.pop();
	return S_OK;
};
STDMETHODIMP MyQueue::front(PERSON &t) {
	t = q.front();
	return S_OK;
};
STDMETHODIMP MyQueue::back(PERSON &t) {
	t = q.back();
	return S_OK;
};
STDMETHODIMP MyQueue::size(int &c) {
	c = q.size();
	return S_OK;
};


STDMETHODIMP MyQueue::QueryInterface(REFIID riid, void ** ppvObject)
{
	if (riid == IID_IUnknown || riid == IID_IMyQueue) {
		this->AddRef();
		*ppvObject = (LPVOID) this;
		return S_OK;
	}
	else
		return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE MyQueue::AddRef(void)
{
	ULONG c = InterlockedIncrement(&refc);
	return  c;
}

ULONG  STDMETHODCALLTYPE MyQueue::Release(void)
{
	ULONG c = InterlockedDecrement(&refc);
	if (c == 0) 	delete this;
	return c;
}

extern "C" __declspec(dllexport) IMyQueue* WINAPI getO() {
	IMyQueue *p = new MyQueue();
	return p;
}

...
Рейтинг: 0 / 0
03.02.2017, 13:59
    #39398156
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Изопропил,

Спасибо большое, все работает.
...
Рейтинг: 0 / 0
07.02.2017, 16:41
    #39400264
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Изопропилvadipok,

с возвратом массива и C-строками :
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    struct PERSON
    {
        public int id;
        [MarshalAs(UnmanagedType.LPStr)]
        public string name;
        public int age;
        public int sex;
    }

 [DllImport(@"C:\VC\Test05\Debug\cdll.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int getA([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref   PERSON[] p, ref int c);



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
struct PERSON1
{
	int   id;
	char* name;
	int   age;
	int   sex;
};


extern "C" __declspec(dllexport) void  WINAPI getA(PERSON1 ** p, int *c)
{
	if ( *p) {
		for (int i = 0; i < *c; i++) {
			::CoTaskMemFree((*p)[i].name);
			(*p)[i].name = nullptr;
		}
		::CoTaskMemFree(*p);
		*p = nullptr;
	}
	
	size_t sz = 10;
	PERSON1 *pt = (PERSON1*)CoTaskMemAlloc(sz*sizeof PERSON1);
	memset(pt, 0, sz * sizeof PERSON1);
	 
	 pt->age = 800;
	 std::string n = "asdf";
	 pt->name = (char*)::CoTaskMemAlloc(n.length()+1);
	 memcpy(pt->name,  n.c_str(), n.length()+1);

	 *p = pt;
	 *c = sz;
}




Коллега, стыдно просить, а как добавить сюда еще один элемент?
Вдвоем сидим второй день и не можем понять что сделать так, чтобы добавить еще один структ.
На выходе получаем 10 struct, у которого только первый заполнен.
Вроде все понятно что вы тут сделали, но решения не нашел.

В свою защиту могу сказать:
Коллега программирует на С++ лет 20 и то не может понять.
Перерыл Страуструпа, таких примеров там не нашел.
...
Рейтинг: 0 / 0
07.02.2017, 16:42
    #39400265
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
До этого я решал подобные задачи, но только через Queue.
Там конечно на порядок было проще.
...
Рейтинг: 0 / 0
07.02.2017, 21:29
    #39400456
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
vadipok,

10 - это просто для примера. просто нужно указать количество возвращаемых элементов ( может и 0 быть
)
атрибут SizeParamIndex = 1 указывет, что количество элементов в массиве не константой задано, а в параметре с указанным номером( с нуля считая) передаётся (и на входе и на выходе)
...
Рейтинг: 0 / 0
08.02.2017, 06:28
    #39400553
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Изопропилvadipok,

10 - это просто для примера. просто нужно указать количество возвращаемых элементов ( может и 0 быть
)
атрибут SizeParamIndex = 1 указывет, что количество элементов в массиве не константой задано, а в параметре с указанным номером( с нуля считая) передаётся (и на входе и на выходе)

Да, это мы сразу поняли.
Параметр sz отвечает за это.
С этим проблем нет, проблема есть с заполнением.
Ну думаю сегодня разберсусь на работе.
...
Рейтинг: 0 / 0
08.02.2017, 08:05
    #39400564
vadipok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Опять С# pinvoke Cpp dll
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
extern "C" __declspec(dllexport) void  WINAPI getA(PERSON ** p, int *c)
{
	if (*p) {
		for (int i = 0; i < *c; i++) {
			::CoTaskMemFree((*p)[i].name);
			(*p)[i].name = nullptr;
		}
		::CoTaskMemFree(*p);
		*p = nullptr;
	}


	size_t sz = 10;
	PERSON *pt = (PERSON*)CoTaskMemAlloc(sz * sizeof PERSON);
	memset(pt, 0, sz * sizeof PERSON);

	pt[0].age = 800;
	string n = "asdf";
	pt[0].name = (char*)::CoTaskMemAlloc(n.length() + 1);
	memcpy(pt[0].name, n.c_str(), n.length() + 1);

	pt[1].age = 800;
	n = "vadim";
	pt[1].name = (char*)::CoTaskMemAlloc(n.length() + 1);
	memcpy(pt[1].name, n.c_str(), n.length() + 1);



спасибо, все работает
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Опять С# pinvoke Cpp dll / 19 сообщений из 19, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]