Вызов C# от C++, Инвертируйте P/Invoke, Смешанный Режим DLLs и C++ / CLI

Я только что натолкнулся на ошибку, которая потребовала у меня целую вечность, чтобы выяснить это и потенциально может дать вам хороший пример точности плавающего числа.

#include <iostream>
#include <iomanip>

int main(){
  for(float t=0;t<1;t+=0.01){
     std::cout << std::fixed << std::setprecision(6) << t << std::endl;
  }
}

На выходе получается

0.000000
0.010000
0.020000
0.030000
0.040000
0.050000
0.060000
0.070000
0.080000
0.090000
0.100000
0.110000
0.120000
0.130000
0.140000
0.150000
0.160000
0.170000
0.180000
0.190000
0.200000
0.210000
0.220000
0.230000
0.240000
0.250000
0.260000
0.270000
0.280000
0.290000
0.300000
0.310000
0.320000
0.330000
0.340000
0.350000
0.360000
0.370000
0.380000
0.390000
0.400000
0.410000
0.420000
0.430000
0.440000
0.450000
0.460000
0.470000
0.480000
0.490000
0.500000
0.510000
0.520000
0.530000
0.540000
0.550000
0.560000
0.570000
0.580000
0.590000
0.600000
0.610000
0.620000
0.630000
0.640000
0.650000
0.660000
0.670000
0.680000
0.690000
0.700000
0.710000
0.720000
0.730000
0.740000
0.750000
0.760000
0.770000
0.780000
0.790000
0.800000
0.810000
0.820000
0.830000
0.839999
0.849999
0.859999
0.869999
0.879999
0.889999
0.899999
0.909999
0.919999
0.929999
0.939999
0.949999
0.959999
0.969999
0.979999
0.989999
0.999999

Как вы можете видеть после 0,83, точность значительно снижается.

Однако, если я установлю t как double, такой проблемы не будет.

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

16
задан ng5000 1 July 2009 в 11:59
поделиться

2 ответа

Вот ответы, насколько мне известно:

  1. Да
  2. Да, это DLL смешанного режима (Фактически, вы можете сделать один файл вашего собственного проекта C ++ управляемым и создать этот класс C ++ / CLI в этом файле и вызывать код непосредственно из этого файла. Для этого вам даже не нужна отдельная DLL.
  3. C ++ / CLI и Managed C ++ представляют одно и то же. Единственное отличие состоит в том, что в более старой версии до Visual Studio 2003 он назывался Managed C ++. Позже синтаксис был сильно изменен и был переименован в C ++ / CLI. Подробнее см. по этой ссылке .
  4. Да
  5. CLR будет использоваться при каждом вызове управляемой DLL.
22
ответ дан 30 November 2019 в 21:37
поделиться

Обратите внимание, что вы также можете выполнить IL-обход C # dll и статические методы экспорта, которые работают в основном так же, как экспорт в C ++ / CLI. Однако это всегда этап после компиляции, и он имеет некоторые предостережения (которые, кстати, есть и в вашем экспорте C ++ / CLI).

Вы можете использовать ILDASM как для C #, так и для C ++ / DLL CLI, чтобы увидеть, как осуществляется экспорт; это примерно так (из образец в сети ):

// unmexports.il
// Compile with : ilasm unmexports.il /dll
assembly extern mscorlib {}
..assembly UnmExports {}
..module UnmExports.dll
// This flag is important
..corflags 0x00000002
// This instructs the CLR to create a marshaling thunk for the unmanaged caller
..vtfixup [1] int32 fromunmanaged at VT_01
..data VT_01 = int32(0)
..method public static void foo()
{
..vtentry 1:1
..export [1] as foo
ldstr "Hello from managed world"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
2
ответ дан 30 November 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: