powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / C++ передача данных в С# соответствие передаваемых типов
7 сообщений из 7, страница 1 из 1
C++ передача данных в С# соответствие передаваемых типов
    #39328162
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Модератор: Пользуйся тэгом SRC!
Здравствуйте уважаемые ГУРУ!

Функция DLL на с++ в результате работы формирует строку типа _bstr_t
Эту строку нужно передать в код на С#

Делаю ледующим образом:
1. На С# получаю указатель на выделенный блок памяти и передаю его параметром в функцию dll на С++
2. В DLL создается строка с типом _bstr_t ID , которая преобразуется в массив char
и записывается по адресу переданному из С#в параметре

Проблема:
В С# приходит не вся строка, а только "BaseBoard="
Само значение _bstr_t BaseBoard не передается.
То есть передается только константная часть строки ID
Если передать только переменную_bstr_t BaseBoard то выскакивает исключение что передаваемое значение не может быть NULL

Хотя когда DLL функция тестируется как консольное приложение то все работает,
Переменная _bstr_t ID содержит и константную часть и значение переменной _bstr_t BaseBoard.

Помогите пожалуйста найти грабли.
Заранее благодарен всем откликнувшимся .

В С#
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
[DllImport(@"D:\\ProjectsC++\\DLL\\MyDLL\\Debug\\MyDLL.dll",
                        EntryPoint = "GetString",
                        ExactSpelling = true,
                        CallingConvention = CallingConvention.Cdecl)]
 
public static extern int GetString(IntPtr pComputerName); 
 
 
var pComputerName = Marshal.AllocHGlobal(256);
// Вызываем описанную внешнюю функцию
GetString(pComputerName, ref size);
// Переводим результат в управляемый вид
var str = Marshal.PtrToStringUni(pComputerName);
//Освобождаем выделенную память
Marshal.FreeHGlobal(pComputerName);



С++:
Код: 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.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>#
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
 
extern "C" __declspec(dllexport)  int GetString(char *pMemory)
{
    HRESULT hres;
    // Step 1: -------------------------------------------------- 
    // Initialize COM. ------------------------------------------
    hres =  CoInitializeEx(0, COINIT_MULTITHREADED);  
    if (FAILED(hres)) 
    { 
        cout << "Failed to initialize COM library. Error code = 0x"  
            << hex << hres << endl; 
        return 1;                  // Program has failed. 
    }
    // Step 2: -------------------------------------------------- 
    // Set general COM security levels --------------------------
    hres =  CoInitializeSecurity( 
        NULL,  
        -1,                          // COM authentication 
        NULL,                        // Authentication services 
        NULL,                        // Reserved 
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication  
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation   
        NULL,                        // Authentication info 
        EOAC_NONE,                   // Additional capabilities  
        NULL                         // Reserved 
        );
    if (FAILED(hres)) 
    { 
        cout << "Failed to initialize security. Error code = 0x"  
            << hex << hres << endl; 
        CoUninitialize(); 
        return 1;                    // Program has failed. 
    }      
    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------
    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance( 
        CLSID_WbemLocator,              
        0, 
        CLSCTX_INPROC_SERVER,  
        IID_IWbemLocator, (LPVOID *) &pLoc);
 
    if (FAILED(hres)) 
    { 
        cout << "Failed to create IWbemLocator object." 
            << " Err code = 0x" 
            << hex << hres << endl; 
        CoUninitialize(); 
        return 1;                 // Program has failed. 
    }
    // Step 4: -----------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method 
    IWbemServices *pSvc = NULL; 
    // Connect to the root\cimv2 namespace with 
    // the current user and obtain pointer pSvc 
    // to make IWbemServices calls. 
    hres = pLoc->ConnectServer( 
         _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace 
         NULL,                    // User name. NULL = current user 
         NULL,                    // User password. NULL = current 
         0,                       // Locale. NULL indicates current 
         NULL,                    // Security flags. 
         0,                       // Authority (for example, Kerberos) 
         0,                       // Context object  
         &pSvc                    // pointer to IWbemServices proxy 
         );   
 
    if (FAILED(hres)) 
    { 
        cout << "Could not connect. Error code = 0x"  
             << hex << hres << endl; 
        pLoc->Release();      
        CoUninitialize(); 
        return 1;                // Program has failed. 
    }
    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
    // Step 5: -------------------------------------------------- 
    // Set security levels on the proxy -------------------------
    hres = CoSetProxyBlanket( 
       pSvc,                        // Indicates the proxy to set 
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx 
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx 
       NULL,                        // Server principal name  
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx  
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx 
       NULL,                        // client identity 
       EOAC_NONE                    // proxy capabilities  
    );
 
    if (FAILED(hres)) 
    { 
        cout << "Could not set proxy blanket. Error code = 0x"  
            << hex << hres << endl; 
        pSvc->Release(); 
        pLoc->Release();      
        CoUninitialize(); 
        return 1;               // Program has failed. 
    }
  // Step 6: -------------------------------------------------- 
    // Use the IWbemServices pointer to make requests of WMI ----
  // For example, get the name of the operating system 
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery( 
        bstr_t("WQL"),  
        bstr_t("SELECT * FROM Win32_BaseBoard"), 
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,  
        NULL, 
        &pEnumerator); 
    
    if (FAILED(hres)) 
    { 
        cout << "Query for operating system name failed." 
            << " Error code = 0x"  
            << hex << hres << endl; 
        pSvc->Release(); 
        pLoc->Release(); 
        CoUninitialize(); 
        return 1;               // Program has failed.
    }
    // Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------
    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0; 
    while (pEnumerator) 
    { 
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,  
            &pclsObj, &uReturn); 
        if(0 == uReturn) 
        { 
            break; 
        } 
        VARIANT vtProp;
        // Get the value of the Name property 
        hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);  //BSTR vtProp
    _bstr_t BaseBoard(vtProp.bstrVal);
    _bstr_t ID = "BaseBoard=" + BaseBoard; 
    //преобразуем _bstr_t ID в массив char и записываем его по переданному в параметре адресу
    strcpy_s(pMemory, ID.length() + 1, (LPCSTR)ID);
 
        VariantClear(&vtProp); 
        pclsObj->Release(); 
    }
    // Cleanup 
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();
    
    return 0;
}
...
Рейтинг: 0 / 0
C++ передача данных в С# соответствие передаваемых типов
    #39328264
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit,

1)WMI доступен без всяких костылей в c#
2) навскид - _bstr_t - юникодный , strcpy_s - нет,
VARIANT - неплохо бы инициализировать и проверять результат выполнения pclsObj->Get
...
Рейтинг: 0 / 0
C++ передача данных в С# соответствие передаваемых типов
    #39328524
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прошу прощения за не оформленный код . Искал на панели кнопку С++ а надо было SRS/ Учту!
В С# WMI у меня работает. Но мне нужно именно на С++

Я понимаю, что дело в преобразовании типов. Но строковая константа же прокатывает!
А переменная этого же типа не прокатывает.

Я и другие способы передачи пробовал и результат тот же например:

Импорт в С#
Код: plaintext
1.
2.
3.
[DllImport("Test.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string GetSomeText();



Объявление на стороне С++
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
extern "C" {
    __declspec(dllexport) BSTR GetSomeText()
    {
 /*   Фрагмент моего кода   
        VARIANT vtProp;
        // Get the value of the Name property 
        hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);  //BSTR vtProp
    _bstr_t BaseBoard(vtProp.bstrVal);
*/
        _bstr_t result = vtProp.bstrVal;

        return result;
    }
}



В окне отладки vtProp.bstrVal указывается как тип BSTR но возвращается как пустая строка .
Не могу понять где собака порылась...

Подскажите пожалуйста как правильно нужно это сделать.

Спасибо.
...
Рейтинг: 0 / 0
C++ передача данных в С# соответствие передаваемых типов
    #39328527
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit,

с новыми багами!
возвращать нужно result.Detach()

vtProp.bstrVal - что там ? есть нужная юникодная строка? правильная ли длина?
...
Рейтинг: 0 / 0
C++ передача данных в С# соответствие передаваемых типов
    #39328581
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ИзопропилArbit,

с новыми багами!
возвращать нужно result.Detach()

vtProp.bstrVal - что там ? есть нужная юникодная строка? правильная ли длина?

1. Что это за баги?

2. vtProp.bstrVal в окне отладки содержит - BSTR = 0x005205b4 L"PF05TBD8"

3. _bstr_t res = vtProp.bstrVal ;

_bstr_t ID = L"BaseBoard=" + _bstr_t res ; // ID содержит L"BaseBoard=PF05TBD8"

Но в С# получаю только "BaseBoard="

4. если возвращаю _bstr_t res. Detach()

_bstr_t ID = L"BaseBoard=" + res.Detach();

Вылетает системное исключение

Не могу сообразить что к чему...
...
Рейтинг: 0 / 0
C++ передача данных в С# соответствие передаваемых типов
    #39328583
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Когда вылетает исключение то там говорится о некорректности
работы с <comutil.h> //Для работы с классом _bstr_t
...
Рейтинг: 0 / 0
C++ передача данных в С# соответствие передаваемых типов
    #39328589
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit4. если возвращаю _bstr_t res. Detach()

_bstr_t ID = L"BaseBoard=" + res.Detach();

возврат - это
Код: plaintext
1.
return  res.Detach();
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / C++ передача данных в С# соответствие передаваемых типов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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