@Markus Freitag I put together a small sample using VS2019 that illustrates using a C++/CLI DLL to interoperate with a C# class library from unmanaged C++. It consists of a solution with 3 projects (C# class library, C++/CLI DLL and C++ console application). You can get it from https://1drv.ms/u/s!AmnqrCFBv4nDggHoFw90fA7As4eK?e=pXnIqv
What are my options? Calls from C++ C# DLL functions, how?

Hello,
I have a C# DLL. I need to call these functions from C++ unmanaged application which is statically bound, no CLI is possible.
What are my options?
Maybe I don't need a CLI wrapper class. Maybe it is easier. Can you make sample for all three functions, please? Thanks in advance!
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace ManagedCSharp
{
public static class ManagedClass
{
static List<string> ListSerials;
static Dictionary<int, string> DicPosSerial;
public static void ShowValue(ref int value)
{
DialogResult result = MessageBox.Show("C# Message Box", "C# Message Box", MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
value = 1;
ListSerials = new List<string>();
DicPosSerial = new Dictionary<int, string>();
}
else
value = 2;
return;
}
public static string GetOrder(string input)
{
return "[ORDER_RES]|2424245|0793|1000|2421Ad";
}
public static bool SendResult(int pos, string serial)
{
ListSerials.Add(serial);
DicPosSerial.Add(pos, serial);
return true;
}
}
}
.NET CLI
C#
C++
-
RLWA32 30,131 Reputation points
2021-07-10T12:55:40.62+00:00 One option that you may want to consider is to use COM. A managed in-process COM server written in C# can interoperate with an unmanaged C++ COM client. The C++ client can instantiate the managed COM object, call its methods, get/set its properties and sink events fired by the server. No C++/CLI wrappers would be needed.
-
RLWA32 30,131 Reputation points
2021-07-11T08:55:55.99+00:00 -
Markus Freitag 3,101 Reputation points
2021-07-11T12:52:39.17+00:00 You are the best! Thanks a lot.
It looks good for the first one. I'll check it more exactly.
int wmain() { int i = 0; CString strOrder(L"This is a test"); wprintf_s(L"Before value of i is %d\n", i); Call_ShowValue(i); wprintf_s(L"After value of i is %d\n", i); CString s = Call_GetOrder(strOrder); wprintf_s(L"GetOrder returned %s\n", (LPCWSTR)s);
Then I can use all data types double, int string. Right?
namespace CSharpLibrary { public static class ManagedCSharp { static List<string> ListSerials; static Dictionary<int, string> DicPosSerial;
I can now insert a list or a dictionary into this class and fill it.
That must be possible, because of the instantiation I'm not sure if I have
to consider something. What is your opinion?
Background:
I have an old C++ application, this has functions. Depending on the state I have to do something.
The idea is to do it with C#, since I have it easier there.
I need to implement a HttpWeb interface. The main problem.Markus Freitag 3,101 Reputation points2021-07-11T17:39:58.38+00:00 I'm taking a closer look.
I have made a new VS2017 project. So did you. I cannot compile it.Have you made any special settings?
the function cannot be added by the new declaration.
A as DLL Import must not be defined.
Does this not work under VS2017?Sam of Simple Samples 5,466 Reputation points2021-07-11T18:06:39.167+00:00 I am using VS 2017 too and I am unable to open the solution too.
RLWA32 30,131 Reputation points2021-07-11T18:29:39.707+00:00 According to Microsoft you should be able to open and work with VS2019 solutions/projects in VS2017. However, if you have created your own solution and projects then they are likely missing some settings that are needed.
For example, the problem with the __declspec(dllimport) being used in the CliLib project is because you have not added the CLILIB_EXPORTS macro to the C++ prepocessor definitions for all platforms/configurations. For example, the shared project settings for Win32/Debug looks like this in the files shared on OneDrive -
And there are some settings in the CppClient project that your project is probably missing -
Additional library dependency -
and also Additional library directory-
Markus Freitag 3,101 Reputation points2021-07-11T18:35:18.977+00:00 For example, the problem with the __declspec(dllimport) being used in the CliLib project is because you have not added the CLILIB_EXPORTS macro to the C++ prepocessor definitions for all platforms/configurations. For example, the shared project settings for Win32/Debug looks like this in the files shared on OneDrive -
Thanks for the quick response.
I will check it. When we need dllimport?
#ifdef CLILIB_EXPORTS #define CLILIB_API __declspec(dllexport) #else #define CLILIB_API __declspec(dllimport) #endif
Sorry it is not working unde VS2017
Can you upload it for VS2017?
Sam of Simple Samples 5,466 Reputation points2021-07-11T18:39:41.33+00:00 I was able to create a new solution and create relevant projects in the solution and copy the code into the new projects. It works for me that way.
RLWA32 30,131 Reputation points2021-07-11T18:39:52.323+00:00 The code will use dllexport in the CliLib project and dllimport in the CppClient project.
RLWA32 30,131 Reputation points2021-07-11T18:42:41.953+00:00 @Sam of Simple Samples I downloaded the shared VS2019 solution/projects from Onedrive to a VM that has VS2017 installed. After unblocking the zip file I extracted the solution/projects from the zip file. For VS2017 it was necessary to retarget the Windows SDK version and also set the build tools for the CliLib and CppClient projects to v141. After that, everything built without any problem in my test.
Sam of Simple Samples 5,466 Reputation points2021-07-11T18:56:36.22+00:00 Good. I was unwilling to install the build tools into my system but it is reasonable for MarkusFreitag-0088 to do so.
RLWA32 30,131 Reputation points2021-07-11T19:06:39.373+00:00 At your service... This download reflects the few adjustments made to build successfully using VS2017 15.9.36 https://1drv.ms/u/s!AmnqrCFBv4nDggKecy-z3LZF1jOx?e=r30Y32
RLWA32 30,131 Reputation points2021-07-11T19:09:50.337+00:00 Sorry if I used sloppy terminology, I didn't have to install build tools, just reset the platform toolset in the project properties from v142 (VS2019) to v141 (VS2017).
RLWA32 30,131 Reputation points2021-07-11T19:15:27.913+00:00 One last thing -- the solution platforms that build all 3 projects are x86 or x64. The Any CPU solution platform will not build the CliLib and CppClient projects.
Markus Freitag 3,101 Reputation points2021-07-11T20:30:13.607+00:00 The code will use dllexport in the CliLib project and dllimport in the CppClient project.
OK, we make no define inside CppClient, so it is dllimport, right?
RLWA32 30,131 Reputation points2021-07-11T20:34:53.967+00:00 Yes, that's correct.
Markus Freitag 3,101 Reputation points2021-07-11T20:35:19.237+00:00 No works too. Thanks.
Is there a way to put the lib file into the CPP file for the client?
CliLibExports.lib;%(AdditionalDependencies)For delivery to the customer, do I have to include the lib or is the DLL sufficient?
Can you say something about the bottom point, your opinion?namespace CSharpLibrary { public static class ManagedCSharp { static List<string> ListSerials; static Dictionary<int, string> DicPosSerial;
I can now insert a list or a dictionary into this class and fill it.
That must be possible, because of the instantiation I'm not sure if I have
to consider something. What is your opinion?RLWA32 30,131 Reputation points2021-07-11T21:20:29.93+00:00 Is there a way to put the lib file into the CPP file for the client?
CliLibExports.lib;%(AdditionalDependencies)
If you don't want to use project properties you can include a #pragma directive inside CppClient.cpp. For example, --- #pragma comment(lib, "CliLib") --- remember that you still need to ensure that the linker can find the import library by setting project properties or providing path information in the #pragma directive.
For delivery to the customer, do I have to include the lib or is the DLL sufficient?
The CliLib.lib import library would be used for load-time dynamic linking of the C++/CLI dll. Of course, you can also do run-time dynamic linking with LoadLibrary/GetProcAddress too. I recommend sticking with the import library and load-time dynamic linking. The sample used CString because you mentioned you wanted to use it and work with MFC. But my recommendation is to export functions that use plain old data types with extern "C".
I can now insert a list or a dictionary into this class and fill it.
That must be possible, because of the instantiation I'm not sure if I have
to consider something. What is your opinion?Whether or not static classes and their static members meet your needs is up to you. A C++/CLI dll can use non-static class instances and their non-static data also. See static-classes-and-static-class-members
RLWA32 30,131 Reputation points2021-07-11T21:35:52.49+00:00 For a little more info - exporting functions using C++ classes means that the exports must use C++ linkage (i.e., no extern "C"). Consequently, the decorated names are exported. You can see from the following example showing the exported decorated names from the sample CliLib.dll why I recommend sticking with load-time dynamic linking with the import library instead of run-time dynamic linking with LoadLibrary/GetProcAddress.
From the linker map -
Exports
ordinal name
1 ?Call_GetOrder@@YA?AV?$CStringT@_WV?$StrTraitATL@_WV?$ChTraitsCRT@_W@ATL@@@ATL@@@ATL@@AAV12@@Z (class ATL::CStringT<wchar_t,class ATL::StrTraitATL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > > __cdecl Call_GetOrder(class ATL::CStringT<wchar_t,class ATL::StrTraitATL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > > &)) 2 ?Call_SendResult@@YA_NHAAV?$CStringT@_WV?$StrTraitATL@_WV?$ChTraitsCRT@_W@ATL@@@ATL@@@ATL@@@Z (bool __cdecl Call_SendResult(int,class ATL::CStringT<wchar_t,class ATL::StrTraitATL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > > &)) 3 ?Call_ShowValue@@YAXAAH@Z (void __cdecl Call_ShowValue(int &))
Markus Freitag 3,101 Reputation points2021-07-12T13:27:26.357+00:00 The stand-a-one solution (three projects) works. I have now implemented this in the previous application and I get these errors. What can be the cause? What is the solution? Are special settings necessary?
Thanks again for your help!
RLWA32 30,131 Reputation points2021-07-12T13:40:38.64+00:00 Well, there is obviously a difference between the sample solution/projects that I shared and the implementation applied to your previous application.
Share the complete previous application that generated the linker errors on OneDrive to assist us in diagnosing this latest problem.
Markus Freitag 3,101 Reputation points2021-07-12T13:47:52.097+00:00 int i = 0; CString strOrder(L"This is a test"); wprintf_s(L"Before value of i is %d\n", i); Call_ShowValue(i); // ###### this is ok! wprintf_s(L"After value of i is %d\n", i);
Works well. Only if I use CString, then this appears. Something happen with CString.
The main project is too big. In my test app all ok.
Only if I insert in the 'right' project, I got this errors and only with CString. Any idea? Solution?
Or can we use std::stringSomething is missing.....LPCWSTR
RLWA32 30,131 Reputation points2021-07-12T13:49:03.027+00:00 Is your C++/CLI dll an MFC DLL?
RLWA32 30,131 Reputation points2021-07-12T13:55:44.573+00:00 Did you see my question about the C++/CLI dll?
Markus Freitag 3,101 Reputation points2021-07-12T13:59:20.363+00:00 Did you see my question about the C++/CLI dll?
Yes, but is not clear for me.
Is your C++/CLI dll an MFC DLL?
No, the same as in your sample.
RLWA32 30,131 Reputation points2021-07-12T14:41:17.647+00:00 The CStringT class shared by ATL and MFC uses different traits. See the discussion of StringTraits at cstringt-class.
I uploaded a new VS2017 sample that includes an MFC C++/CLI dll and an MFC Console application. Now that both are in sync as far as CStringT is concerned. See https://1drv.ms/u/s!AmnqrCFBv4nDggPOfNJMX-wSHEWg?e=xj2aBG
Markus Freitag 3,101 Reputation points2021-07-12T14:50:14.22+00:00 Thanks,
could you tell me, what you change it? What I need to to?
I need now a mfc DLL, right?
RLWA32 30,131 Reputation points2021-07-12T14:54:35.493+00:00 Yes, if you want to export functions using CString for consumption by an MFC application then you should use an MFC dll as I showed in the sample.
Markus Freitag 3,101 Reputation points2021-07-12T14:58:58.713+00:00 The rest of settings is the same, right?
Thanks.
RLWA32 30,131 Reputation points2021-07-12T15:26:42.523+00:00 Everything is in the sample that was provided. I don't know what you mean by the rest of the settings. Take the time to examine the projects provided and look at their settings. It's not that complicated.
Sam of Simple Samples 5,466 Reputation points2021-07-12T17:52:06.887+00:00 Programmers like to get samples that do exactly what they need to do so they do not need to learn how to do it themselves but they should learn. You have been provided with samples that are very close to what you need. Without the samples you would need to buy a book or multiple books and spend a month or two learning. You still need to spend some time learning about the code you have been provided and understand how it works.
Markus Freitag 3,101 Reputation points2021-07-12T18:47:30.787+00:00 Take the time to examine the projects provided and look at their settings. It's not that complicated.
Yes, right, you have to have done it once. There are a lot of little things that I need to know. I say thank you 1000 times for your help. I will continue to test it tomorrow and let you know. You helped me a lot, I'm glad.
With the MFC dll I didn't know that I needed this. That is certainly not in any book.
IIn review, if the main application is MFC, I might have thought I needed an MFC Dll.
I thought that would have to suffice as at the beginning, since a CString was available for reading.Markus Freitag 3,101 Reputation points2021-07-13T07:13:02.747+00:00 Sorry, it doesn't work, same error. Do you have another idea?
I can no longer debug with the MFC application.
Maybe ???
There is another data type, no CString.
in the MFC application I convert to CString. Is this possible? If so, how?RLWA32 30,131 Reputation points2021-07-13T07:58:23.217+00:00 Just saying"it doesn't work, same error" doesn't tell me much. The MFC C++/CLI dll and the MFC console application that I uploaded in the last sample built and ran without error using VS2017.
Again, there is something different between the samples and what you are actually doing. And because you haven't shared anything with us I'm not going to spend time trying to guess what those differences might be. My last question about this is whether or not you are linking with the import library for the MFC C++/CLI dll? Its import library is named MFCCliLib.lib
At this point I'll repeat my previous suggustion that you use plain old data types (i.e, wchar_t, wchar_t*). If you want to use std::wstring thats up to you but I don't recommend it.
Markus Freitag 3,101 Reputation points2021-07-13T08:24:39.087+00:00 Hello,
I think the problem is CString. Is there any other way to solve it?
At this point I'll repeat my previous suggustion that you use plain old data types (i.e, wchar_t, wchar_t*).
Can you make a sample for whcar_t, please?
CLILIB_API const char* Call_GetOrder(CString& str) { String^ cli_str = gcnew String(str.GetString()); marshal_context^ context = gcnew marshal_context(); const char* result; result = context->marshal_as<const char*>(ManagedCSharp::GetOrder(cli_str)); std::string str2(result); return result;
RLWA32 30,131 Reputation points2021-07-13T08:31:17.123+00:00 You didn't answer my question about linking with the correct import library.
Again, did you link with MFCCliLib.lib?
Markus Freitag 3,101 Reputation points2021-07-13T08:35:36.55+00:00 Sorry.
Yes please do not be angry. We are close to the finish line.
Yes I use the MFCCliLib.
The best is, the last try to use your proposal wchar_t, wchar_t* for interface.
Then in the client I can convert it std:string or CString.Can you help me, how I can do it?
RLWA32 30,131 Reputation points2021-07-13T08:56:35.86+00:00 I'm not angry with you.
But you have to understand that it is a bit frustrating to provide many working samples only to be told that "it doesn't work" when the concepts illustrated are implemented in some unknown way. So using samples as cut and past solutions hasn't worked yet.
Lets do something different this time. I think all the previously provided samples have given you lots of guidance to follow and there is plenty of available documentation about converting strings from one type to another.
So I suggest you create your own sample and share it with us if there are problems. I do want you to succeed and am happy to provide further assistance.
Markus Freitag 3,101 Reputation points2021-07-13T09:06:52.447+00:00 CLILIB_API const char* Call_GetOrder(CString& str) { String^ cli_str = gcnew String(str.GetString());
Please show me how I can use wchar inside our interface. I think the problem is on CString.
RLWA32 30,131 Reputation points2021-07-13T09:13:16.43+00:00 No, I'm not writing more code for you to mechanically cut and paste into some other application. I'll help you debug your own code if you need it.
Markus Freitag 3,101 Reputation points2021-07-13T09:23:38.797+00:00 Yes you are angry with me.
The client project is very big, I can't send it. I tried to keep it small.Please, please just one more try the Liberary with wchar.
No project just a code how the conversion would go,
otherwise I have to implement a socket interface, which is not easier.#pragma once #ifdef CLILIB_EXPORTS #define CLILIB_API __declspec(dllexport) #else #define CLILIB_API __declspec(dllimport) #endif #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS #include <atlstr.h> #include <string> //#include <msclr/marshal_cppstd.h> CLILIB_API void Call_ShowValue(int& i); //CLILIB_API CString Call_GetOrder(CString& str); CLILIB_API wchar_t Call_GetOrder(CString& str); //CLILIB_API String^ Call_GetSerial(CString& str); //CLILIB_API std::string Call_GetOrder2(CString& str); CLILIB_API bool Call_SendResult(int pos, CString& serial);
#include <stdlib.h> #include <string.h> #include <msclr\marshal.h> using namespace msclr::interop; using namespace CSharpLibrary; using namespace System; CLILIB_API void Call_ShowValue(int& i) { ManagedCSharp::ShowValue(i); } CLILIB_API wchar_t Call_GetOrder(CString& str) { String^ cli_str = gcnew String(str.GetString());
RLWA32 30,131 Reputation points2021-07-13T10:29:51.717+00:00 I was considering changing my mind about providing yet another sample solution for you when I saw your new question at c-c-cli-library-convert-string-to-wchar-or-wchar.html in which you copied the code I provided, took credit for it and failed to exert any effort to find your own solution.
You have disappointed me, disrespected me and made me feel that all my effort to help you has been a waste of my time.
Markus Freitag 3,101 Reputation points2021-07-13T11:09:29.3+00:00 I'm sorry. I'm deleting this again.
Please understand me, I need a solution.
You were nice to help, I apologise.What do i have to do for another sample solution?
RLWA32 30,131 Reputation points2021-07-13T11:21:18.4+00:00 Apology accepted.
In C++/CLI dll
MFCCLILIB_API wchar_t* Call_GetOrder2(CString & str) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); String^ cli_str = gcnew String(str.GetString()); String^ strresult = ManagedCSharp::GetOrder(cli_str); marshal_context context; const wchar_t* pwsz = context.marshal_as<const wchar_t*>(strresult); // Converted string must be copied before function returns // Use Com Task Allocator to avoid CRT issues when passing memory across dll boundaries // Caller must free memory with CoTaskMemFree size_t nChars = wcslen(pwsz) + 1; // add 1 for null terminator wchar_t* pwszReturn = static_cast<LPWSTR>(CoTaskMemAlloc(nChars * sizeof(WCHAR))); wcscpy_s(pwszReturn, nChars, pwsz); return pwszReturn; }
In MFC client -
CComHeapPtr<wchar_t> pwszOrder; // Frees memory using CoTaskMemFree in destructor pwszOrder.Attach(Call_GetOrder2(strOrder)); wprintf_s(L"GetOrder2 returned %s\n", static_cast<wchar_t*>(pwszOrder));
Markus Freitag 3,101 Reputation points2021-07-13T15:03:31.637+00:00 Thank you for accepting the apology.
Maybe you can say something else, otherwise I'll have to choose another interface.
The thread is long, the problem is difficult, which is the reason.I have asked you to support me. You did it freely. For that I said and still say thank you.
I can't publish the whole project because it's not mine. I tried to reduce it to a fragment.The project is written in VS2010 and cannot be changed to a newer version.
Your sample projects all worked. I thought it was no problem to implement this in the main application.
I failed, it doesn't work.The same problem always occurs, CString, but also with your last suggested solution.
Integer works without any problems.
My idea would be to leave the interface void and work with references.//Client char* input = new char[4096]; char* output = new char[4096]; Call_Panel(i, input, output); CString output1(output);
Compile is ok, but
is not filled, I am doing something wrong with the pointers. Do you see the error?CLILIB_API void Call_Panel(int& i, char* input, char* output); // new test function, calls the existing function serial
RLWA32 30,131 Reputation points2021-07-13T15:16:17.193+00:00 This has really turned into a moving target. I thought you were working with VS2017. Now all of a sudden VS2010 enters the picture.
Again you only said that my last suggestion which used CoTaskMemAlloc didn't work. You need to be specific about the problems encountered. I can't see any reason why the last bit of code that I suggested should be problematic unless it's related to VS2010 since the code was tested with VS2017 and functioned properly.
So before I start going down a different path I'd like a complete explanation. Thank you.
Markus Freitag 3,101 Reputation points2021-07-13T16:01:52.907+00:00 Here is my code with pragma and first without MFC. So it is easier.
RLWA32 30,131 Reputation points2021-07-13T17:21:08.237+00:00 The code in your shared project is NOT what I posted and contains errors.
I could not open your shared solution/projects in VS2010 so I created a new VS2010 Solution/projects with appropriate corrections that builds and runs without error - https://1drv.ms/u/s!AmnqrCFBv4nDggUHS3akfbtJB_yV?e=E2xsQE
Markus Freitag 3,101 Reputation points2021-07-13T19:04:23.117+00:00 Yes, thank you very much. I can test it tomorrow. I hope this solves the CString problem.
Markus Freitag 3,101 Reputation points2021-07-14T05:52:29.33+00:00 Good Morning!
Sorry again
for the disturbance. Your application works. My client does not work string problems. Something is missing. Do you have an idea please?Timon Yang-MSFT 9,516 Reputation points2021-07-14T08:23:05.8+00:00 Could you please translate the error message into English and provide it to us?
Is the error you encountered the same as in the link?
Why is the error E0413 occurring in system() in C++?RLWA32 30,131 Reputation points2021-07-14T08:24:48.8+00:00 Are you talking about the CppWrapper solution/projects that you shared with me?
Also, I have a feeling that you may have mismatches beetwen MFC and the CRT used in your various projects. For example building with v100 platform toolset in one project and v142 platform toolset in another, or maybe using static libraries in one project but dll libraries in another.
I could not load your CppWrapper in VS2010 so I went back and loaded it in VS2017. I did not let VS2017 update the solution when it loaded. I saw platform toolset differences in some of the project settings. I don't know if this is what you are working with but it would definitely be a problem if it is.
You should consider changing all parameter passing to use wchar_t* instead of CString references. That would probably eliminate the problem but you would need to be careful about memory allocation and crossing dll boundaries.
potential-errors-passing-crt-objects-across-dll-boundariesMarkus Freitag 3,101 Reputation points2021-07-14T08:38:06.943+00:00 What I must compare, to check it?
Markus Freitag 3,101 Reputation points2021-07-14T08:40:37.827+00:00 Reference to unresolved internal symbol
RLWA32 30,131 Reputation points2021-07-14T08:44:01.58+00:00 I don't understand the German, but I can see that you have a character set mismatch. One of your projects is UNICODE and the other is MBCS.
Markus Freitag 3,101 Reputation points2021-07-14T08:49:42.107+00:00 Yes I changed, same error.
RLWA32 30,131 Reputation points2021-07-14T08:50:54.87+00:00 And the same problem as before an MFC client using the MFC version of CString passing parameters to/from a C++CLI dll that is NOT an MFC dll and so it would use the ATL version of CString. Remember the StringTraits issue?
Markus Freitag 3,101 Reputation points2021-07-14T09:43:53.503+00:00 Is the same with MFC DLL.
#ifdef MFCCLILIB_EXPORTS #define MFCCLILIB_API __declspec(dllexport) #else #define MFCCLILIB_API __declspec(dllimport) #endif MFCCLILIB_API void Call_ShowValue(int& i); MFCCLILIB_API void Call_Func1(char* input, char*output, int& result); // MFCCLILIB_API CString Call_GetOrder(CString& str); MFCCLILIB_API bool Call_SendResult(int pos, CString& serial); MFCCLILIB_API wchar_t* Call_GetOrder2(CString& str);
Void works well.
So the idea I use only void with reference as result.
But is difficult, memory leak and how to initialize it, right?RLWA32 30,131 Reputation points2021-07-14T09:52:01.86+00:00 As I previously suggested, stop using CString as a function parameter or return type. I definitely would not use void* pointers. Pass or return wchar_t* or char* as needed.
It is unfortunate that you cannot share your actual projects. As the various working sample projects have demonstrated, the problem resides somewhere that we have no access to and are left to guess. So to me, eliminating CString is the best alternative.
RLWA32 30,131 Reputation points2021-07-14T10:21:53.753+00:00 Another thought occurred to me - Your MBCS MFC Client must work with an MBCS MFC C++/CLI Dll. So did you deal with both issues at the same time?
Markus Freitag 3,101 Reputation points2021-07-14T11:45:32.977+00:00 Your MBCS MFC Client must work with an MBCS MFC C++/CLI Dll. So did you deal with both issues at the same time?
Not really.
So to me, eliminating CString is the best alternative.
The last try. Can you make here a sample.
char* input = new char[4096]; char* output = new char[4096]; //Call_Panel(i, input, output);
works also not
The client use not CLI. I not allowed from my boss to switch to CLI. Reason, the whole project works not.
RLWA32 30,131 Reputation points2021-07-14T11:53:42.657+00:00 Your MBCS MFC Client must work with an MBCS MFC C++/CLI Dll. So did you deal with both issues at the same time?
Not really.
For all I know that could be the cause of your CString problem. You already have the samples with the MFC C++/CLI dll and the MFC Console application. Why don't you change the character sets (all platforms/all configurations) to MBCS and rebuild? You would need to change the console printing to use their MBCS equivalents (or comment them out).
Before I write more code I want you to test an MBCS MFC C++/CLI dll.
Markus Freitag 3,101 Reputation points2021-07-14T19:18:07.007+00:00 Your MBCS MFC Client must work with an MBCS MFC C++/CLI Dll.
You mean the settings of the Client?
You mean also the character sets? I change it, both use the same. (Multibyte) Nothing happen, same error.
RLWA32 30,131 Reputation points2021-07-14T19:33:53.53+00:00 I cannot tell from your comment if you performed the test that I requested. Sometimes it seems that you don't fully understand what has to be done.
Did you build an MBCS version of the MFC C++/CLI dll using the v100 toolset and test that with your VS2010 project MBCS MFC application?
Did you build the VS2010 MBCS MFC application with the MBCS MFC C++/CLI dll's import library?
If you did as I requested in the MBCS testing and the link errors still occurred post their complete text so I can see them. Thank you.
Also, in a developer command prompt please run dumpbin /exports against the MBCS MFC C++?CLI dll and post the results.
Markus Freitag 3,101 Reputation points2021-07-15T06:36:10.647+00:00 Yes you are the best.
My mistake
Multibyte character set (MBCS) I did it in CLibExports. I forgot it in MFCLibExport.please run dumpbin /exports
Can you say more about that? Where? See also picture.
I can't debug it. Why?
it would be very helpful if I could debug. Everything is in a project folder. Are settings necessary?Thanks for your help and answer!
CString s = Call_GetOrder(strOrder); //wprintf_s(L"GetOrder returned %s\n", (LPCWSTR)s); wprintf_s(L"GetOrder returned %s\n", s);
(LPCWSTR)s); is not possible, why?
RLWA32 30,131 Reputation points2021-07-15T07:53:29.483+00:00 If you have gotten everything configured so that MBCS is the character set for all of the projects then CString now encapsulates a char*, not a wchar_t*. Keeping this in mind the (LPCWSTR) cast is for use with Unicode. Now that you are working with an MBCS build you should use (LPCSTR) and change the printing statements to use printf_s instead of wprintf_s. That should solve any compilation problems related to printing.
Visual Studio installs a number of helpful standalone utilities. One of these is dumpbin.exe. It is run from a command prompt. Your Visual Studio installation should have installed start menu items to enable you to open a developer command prompt window. This is a command prompt window in which all of the necessary environment variables and paths to run Visual Studio programs from the command line have been set for you. So remove anything you put in a project properties related to dumpbin. If you have gotten far enough to have debugging questions then running dumpbin should not be necessary since it would seem you have a successful build!
During your debugging the debugger is attempting to step into code that resides in the Common Language Runtime assembly (clr) but symbols are not available for this. You can use breakpoints before/after such code and not try to debug into the clr. If such message boxes appear close them and use F5 to run to the next breakpoint.
RLWA32 30,131 Reputation points2021-07-15T08:14:05.447+00:00 These comments are limited ton 1600 characters. What an annoyance.
Anyway, you can tell Visual Studio's debugger to download symbol files for the various system dll's/assemblies that are loaded into a process during a debugging session. Most of the time this is not necessary since you are really interested in stepping through your own code. For more information see specify-symbol-dot-pdb-and-source-files-in-the-visual-studio-debugger
It is also possible to use the same code for both MBCS or UNICODE builds if you write your code to use generic functions and data types. If you include tchar.h either directly or indirectly then you can use a print statement like this for both of the two character sets
_tprintf_s(_T("Print some text : %s\n"), (LPCTSTR) s);
Markus Freitag 3,101 Reputation points2021-07-15T08:51:49.557+00:00 Hello,
sorry it is not clear for me.
Can you make a sample?
Debugging from C++ to C# is not possible, right? Some setting maybe?
public static string GetOrder(string input) { MessageBox.Show(input, "GetOrder"); return "ABCD"; } public static bool SendResult(int pos, string serial) {
OK I saw it to late your proposal, I will read it. https://learn.microsoft.com/en-us/visualstudio/debugger/specify-symbol-dot-pdb-and-source-files-in-the-visual-studio-debugger?view=vs-2019
[specify-symbol-dot-pdb-and-source-files-in-the-visual-studio-debugger][2]
Markus Freitag 3,101 Reputation points2021-07-15T09:07:16.517+00:00 OK also not so easy.
how would you read that? How to configure? This way isn't work
RLWA32 30,131 Reputation points2021-07-15T09:47:12.937+00:00 This is the setting that I use to retrieve symbols from Microsoft's symbol server-
This is how to use dumpbin.exe -
Markus Freitag 3,101 Reputation points2021-07-15T12:30:59.66+00:00 Can you debug it with your settings?
The symbols loaded, but goes not inside the function.
RLWA32 30,131 Reputation points2021-07-15T12:37:22.777+00:00 Yes, I can debug into the C++/CLI dll and the C# class library with my settings. You need to check your settings to make sure you are using debug builds, that you have created the .pdb files for the debugger and that you are using the mixed mode debugger.
BTW, hasn't your posted question been answered? And then some!!!!
Also, you cannot expect to do source code debugging inside Microsoft's dlls and assemblies! Did you check the "Just My Code" setting in the Visual Studio debugging setting?
Markus Freitag 3,101 Reputation points2021-07-15T18:26:19.42+00:00 BTW, hasn't your posted question been answered?
Sure!
And thank you very much. It was a long thread, but very helpful.RLWA32 30,131 Reputation points2021-07-15T19:07:49.357+00:00 You're welcome. Yes, we have covered a lot of ground. But I'm very happy that we were able to bring everything to a successful conclusion.
Sign in to comment2 additional answers
Sort by: Most helpful
-
Sam of Simple Samples 5,466 Reputation points
2021-07-10T15:27:55.613+00:00 In your first version of this question at C# to C++/MFC duplex mode - Concept I did not understand that the reason you think you cannot modify the MFC application is the static linking. See Managed C++ Wrapper For Unmanaged Code. Believe it or not, you can use C++/CLI in a C++ program that is statically linked. I wrote the original article from code I wrote to call Microsoft Detours, which is (was) only available as a static library. You can add C++/CLI to an existing C++ application such as a MFC application.
-
Markus Freitag 3,101 Reputation points
2021-07-10T19:26:30.747+00:00 Hello @Sam of Simple Samples ,
public static void ShowValue(ref int value) public static string GetOrder(string input) public static bool SendResult(int pos, string serial)
You can add C++/CLI to an existing C++ application such as a MFC application
I think is difficult, can you show how you would do it with my three functions? Thanks in advance.
Sign in to commentrupesh shukla 16 Reputation points2021-07-14T21:53:42.16+00:00 -
Markus Freitag 3,101 Reputation points
2021-07-15T18:26:42.73+00:00 Thanks for the link!
Sign in to comment -
-
That looks complicated. Can't it be simpler and do you have a concrete example available? Thanks in advance.
Perhaps via CLI after all. But how and where do I integrate the DLL into the C++ application? Or is it only possible via DLL import and I only have to specify the path? Do you have an example here?
I googled but there is no short striking example of how to do it. Is so difficult for me in this case.
Its old but I have shared a C# COM Server sample for you on OneDrive at https://1drv.ms/u/s!AmnqrCFBv4nDgX6F7i4pxFQfzHBm?e=NOyJOs
Another possibility is to use delegates and function pointers. An example of calling back into C# from a C++ dll is at https://1drv.ms/u/s!AmnqrCFBv4nDggCbJ7WXNnfm4lzG?e=HTI2tH
Also, take a look at Calling-Csharp-NET-methods-from-unmanaged-C-Cplusp
Hello @RLWA32 ,
Thanks for your help!
Calling-Csharp-NET-methods-from-unmanaged-C-Cplusp
I think this is the best solution for me. Can you please help me how to call the 3 functions of my C# class, how to declare them. Thanks in advance.
I mean this.
and now my three functions.
-------------
How would I have to define that? That is my problem now.
Sign in to comment