У меня есть следующий код C# (sample.dll).не удалось запустить неуправляемый тест модуля cpp для управляемого кода
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Sample
{
public class Worker
{
/// <summary>
/// Callback method signature to send array of values.
/// </summary>
/// <param name="values">The values.</param>
public delegate void FloatValuesReady(float[] values);
/// <summary>
/// Occurs when [float values are ready].
/// </summary>
public event FloatValuesReady ReadFloatValues;
/// <summary>
/// Sums the specified i.
/// </summary>
/// <param name="i">The i.</param>
/// <param name="j">The j.</param>
/// <returns></returns>
public int Sum(int i, int j)
{
return i + j;
}
/// <summary>
/// Gets the Student object.
/// </summary>
/// <returns></returns>
public ManagedStudent GetStudent()
{
Console.WriteLine("Enter a Name:");
string text = Console.ReadLine();
if (text != string.Empty)
{
return new ManagedStudent { Name = text };
}
return new ManagedStudent { Name = "NoName" };
}
/// <summary>
/// Read some float values from Console and give it back to the caller using ReadFloatValues callback.
/// So Caller should add event handler to ReadFloatValues event.
/// </summary>
public void GetSomeFloatValues()
{
List<float> values = new List<float>();
Console.WriteLine("Enter 4 valid float values for the Native App");
while (values.Count < 4)
{
string valueText = Console.ReadLine();
float value;
if(float.TryParse(valueText, out value))
{
values.Add(value);
}
}
if (this.ReadFloatValues != null)
{
this.ReadFloatValues(values.ToArray());
}
}
}
/// <summary>
/// A Managed Class
/// </summary>
public class ManagedStudent
{
public string Name { get; set; }
}
}
Я создал C++ обертки для вышеприведенного sample.dll для Асесса управляемого кода в неуправляемом коде (wrapper.dll). Ниже приведен код для SampleWrapper.h, SampleWrapper.cpp, NativeInterface.h.
/*Sample Wrapper.h*/
using namespace System;
using namespace Sample;
namespace Wrapper
{
public ref class SampleWrapper
{
/* Private Constructor to achieve signle ton*/
SampleWrapper(void)
{
workerObj = gcnew Worker();
workerObj->ReadFloatValues += gcnew Worker::FloatValuesReady(this, &Wrapper::SampleWrapper::FloatArrayReadyMethod);
}
public:
Worker^workerObj;
/* Static reference to single ton instace.
In order to use applications built in C.*/
static SampleWrapper^Instance = gcnew SampleWrapper();
void FloatArrayReadyMethod(array<float>^values);
};
}
/*NativeInterface.cpp/*
#ifdef __cplusplus
extern "C"
{
#endif
/* Un managed type definition of student equalent to the Managed*/
typedef struct
{
char* name;
}UnManagedStudent;
/* A simple interface using the premitive types. Accepts 2 paramters and retun*/
__declspec(dllexport) int SumFromCSharp(int i, int j);
/* An interface to get the Student Information in a Structure.
This function calls the C# class method and gets the managed Student Object
and converts to unmanged student*/
__declspec(dllexport) UnManagedStudent GetStudent();
/* Function pointer to a native function to achieve call back*/
typedef void (*GetFloatArrayCallback) (float values[], int length);
/* An interface that makes call to C# to read some float values.
The C# worker respond back in event call back.
In order to pass the information back to the native app
it should give the callback pointer*/
__declspec(dllexport) void GetFloatArrayFromCSharp(GetFloatArrayCallback cb);
#ifdef __cplusplus
}
#endif
/*sampleWrapper.cpp*/
#include "SampleWrapper.h"
#include "NativeInterface.h"
using namespace Sample;
namespace Wrapper
{
#ifdef __cplusplus
extern "C"
{
#endif
void copyManagedStringToCharPointer(char target[], System::String^inputString)
{
int maxSize = inputString->Length;
if (maxSize > 0)
{
for (int index = 0; index < maxSize; ++index)
{
target[index] = (char)inputString->default[index];
}
target[maxSize] = '\0';
}
}
void copyManagedFloatToUnfloatArray(float target[], array<float>^values)
{
int maxSize = values->Length;
if (maxSize > 0)
{
for (int index = 0; index < maxSize; index++)
{
target[index] = (float)values[index];
}
}
}
__declspec(dllexport) int SumFromCSharp(int i, int j)
{
Worker^worker = SampleWrapper::Instance->workerObj;
return worker->Sum(i,j);
}
__declspec(dllexport) UnManagedStudent GetStudent()
{
Worker^worker = SampleWrapper::Instance->workerObj;
ManagedStudent^studentObj = worker->GetStudent();
String^mName = studentObj->Name;
UnManagedStudent studentStruct;
studentStruct.name = new char[mName->Length];
copyManagedStringToCharPointer(studentStruct.name,mName);
return studentStruct;
}
GetFloatArrayCallback floatArrayCallback;
__declspec(dllexport) void GetFloatArrayFromCSharp(GetFloatArrayCallback cb)
{
floatArrayCallback = cb;
Worker^worker = SampleWrapper::Instance->workerObj;
worker->GetSomeFloatValues();
}
void SampleWrapper::FloatArrayReadyMethod(array<float>^values)
{
float *nativeValues = new float[values->Length];
copyManagedFloatToUnfloatArray(nativeValues, values);
floatArrayCallback(nativeValues, values->Length);
}
#ifdef __cplusplus
}
#endif
}
#include "DemoNativeDll.h"
#include "NativeInterface.h"
using namespace nsNativeDll;
CDemoNativeDll::CDemoNativeDll(void)
{ }
CDemoNativeDll::~CDemoNativeDll(void)
{
}
int CDemoNativeDll::GetSum(int value1, int value2)
{
return SumFromCSharp(value1,value2);
}
Затем я создал блок случае Native.dll ниже
#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\NativeDll\DemoNativeDll.h"
#include "..\Wrapper\NativeInterface.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace nsNativeDll;
namespace UnitTest1
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
CDemoNativeDll* obj = new CDemoNativeDll();
int sum = obj->GetSum(10,15);
Assert::AreEqual(sum,15);
// TODO: Your test code here
}
};
}
Я получаю исключение EEFileLoadException. Как перенаправить это исключение. Я использую Visual Studio 2012 cppunit.