powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Опять С# pinvoke Cpp dll
19 сообщений из 19, страница 1 из 1
Опять С# pinvoke Cpp dll
    #39397261
vadipok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день, коллеги!

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

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
Опять С# pinvoke Cpp dll
    #39397315
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vadipokстеком структуры
что это?
...
Рейтинг: 0 / 0
Опять С# pinvoke Cpp dll
    #39397360
vadipok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилvadipokстеком структуры
что это?

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

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

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

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

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

Добрый день, спасибо за совет.
Скиньте плиз пример, если это возможно.
Или ссылку на туториал.
...
Рейтинг: 0 / 0
Опять С# pinvoke Cpp dll
    #39397807
vadipok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С просто 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
Опять С# pinvoke Cpp dll
    #39397810
vadipok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересное конечно решение, тут получается мы передаем переменную, она там присваивается и возвращается обратно.
Я не думал что они так плотно могут работать между собой.
...
Рейтинг: 0 / 0
Опять С# pinvoke Cpp dll
    #39397830
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vadipokС просто struct то же разобрался, остается сделать из него array queue или еще что ни будь.
Код: c#
1.
Queue<Name> result;


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


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



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

Спасибо большое, все работает.
...
Рейтинг: 0 / 0
Опять С# pinvoke Cpp dll
    #39400264
vadipok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил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
Опять С# pinvoke Cpp dll
    #39400265
vadipok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
До этого я решал подобные задачи, но только через Queue.
Там конечно на порядок было проще.
...
Рейтинг: 0 / 0
Опять С# pinvoke Cpp dll
    #39400456
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vadipok,

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

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

Да, это мы сразу поняли.
Параметр sz отвечает за это.
С этим проблем нет, проблема есть с заполнением.
Ну думаю сегодня разберсусь на работе.
...
Рейтинг: 0 / 0
Опять С# pinvoke Cpp dll
    #39400564
vadipok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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
19 сообщений из 19, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Опять С# pinvoke Cpp dll
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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