Project

General

Profile

Common Language Runtime support

Если есть желание использовать одновременно управляемый и неуправляемый код в реализации и при этом не собирать полностью весь проект с опцией /clr,

необходимо в настройках нужного cpp файла включить опцию /clr и отключить несовместимые с ней опции - /RTC1, /Gm, /EHsc, /Yu, /ZI.

Для примера рассмотрим кусочек кода, который кодирует строку с помощью .NET объекта Encoder.

1. Создадим Win32 Concole Application проект (clr_test.vcproj).

2. Редактируем свойста clr_test.cpp согластно описанию рассмотренному выше.

3. Напишем реализацию кодировщика с помощью функции .NET.

3.1 Подключаем необходимые заголовочники и нэймспэйсы.

#include "stdafx.h"
#include
#include

#using <mscorlib.dll>
using namespace System;

3.2 Прагма managed заставляет генерировать компилятор управляемый код

#pragma managed

3.3 Реализация кодирования строки в Base64 строку.

array<unsigned char>^ GetData(const char* pData, size_t count) 
{

  array<unsigned char>^ myArray = gcnew array<unsigned char>(count);
  for (size_t i = 0; i < count; ++i)
    myArray[i] = pData[i]; 

  return myArray;


}
String^ Base64Encode(const std::string& encodeStr, int strLen) 
{

 array<unsigned char>^ binaryData = GetData(encodeStr.c_str(), strLen);
 return Convert::ToBase64String(binaryData);

}
std::string EncodeData(const std::string& encodeStr) {

  String^ result = Base64Encode(encodeStr, encodeStr.length());
 IntPtr obj = Marshal::StringToHGlobalAnsi(result);
 char* res = (char*)(void*)obj; 
 std::string data(res);
 Marshal::FreeHGlobal(obj);
 return data;
}

3.4 Прагма unmanaged заставляет генерировать компилятор неуправляемый код

#pragma unmanaged

3.5 Используем функции реализованные в секции неуправляемого кода

int main(int argc, _TCHAR* argv[]) 
{
  std::string str = "Hello world!";
   std::cout << "Begin: " << str << "\n";


  str = EncodeData(str);
   std::cout << "Encode: " << str << "\n";
   return 0;

}
  1. Окошко консольной программы.

{{Image("clr_view1.JPG","nolink")}}

5. Теперь скомпилируем простой пример с опцией компилятора /FAs (C/C -> Output Files-> Assembler output) - Assembly with source code и посмотрим что получилось.

Пример:

static int var; 
 void test2(); 



#pragma unmanaged 
 void test1() 
 {

  var = 1; 
   test2(); 


} #pragma managed 



void test2() 
 {
  var = 1;
   test1();  
 }

Результат:

.bss
 .local        _var,4
 .text

.global        ?test2@@$$FYAXXZ                                ; test2
 ?test2@@$$FYAXXZ:                                        ; test2

  ldc.i.1                1                ; i32 0x1
   stsfld                _var
   call                ?test1@@$$FYAXXZ
   ret

  .end ?test2@@$$FYAXXZ                                        ; test2


_TEXT        ENDS
 PUBLIC        +mep@?test2@@$$FYAXXZ
 PUBLIC        ?test2@@YAXXZ                                        ; test2
+

data        SEGMENT
 +mep@?test2@@$$FYAXXZ TOKEN 0A00000C
 data        ENDS
+

_TEXT        SEGMENT
 ?test2@@YAXXZ PROC                                        ; test2, COMDAT

  jmp        DWORD PTR +mep@?test2@@$$FYAXXZ
+

?test2@@YAXXZ ENDP                                        ; test2
 _TEXT        ENDS
 PUBLIC        ?test1@@YAXXZ                                        ; test1

_TEXT        SEGMENT
 ?test1@@YAXXZ PROC                                        ; test1

  push        ebp
   mov        ebp, esp
   mov        DWORD PTR _var, 1
   call        ?test2@@YAXXZ                                ; test2
   pop        ebp
   ret        0


?test1@@YAXXZ ENDP                                        ; test1
 _TEXT        ENDS
 END

Можно увидеть, что в одном модуле у нас нормально живут MSIL и ассемблер. В обоих случаях вызов функций производится через специальные заглушки. Обращение к переменной происходит напрямую в обоих случаях, с той лишь разницей, что каждая функция делает это по-своему.

Add picture from clipboard (Maximum size: 742 MB)