Hey. I'm trying to get this code http://www.codeguru.com/Cpp/W-P/files/inifiles/article.php/c4455/#more to compile under a CLR WinForms app I'm making.
But what is the right syntax? A CString under CLR is to be written System::String but what about CStringList? (I figure it's a string array)
What do you mean by CLR equivalent?
If you mean plain C# then this will do:
string[] arr = new string[size];
or:
List<String> list = new List<String>();
If you mean C++/CLI by CLR equivalent then something like this should work:
array<String^>^ arr = gcnew array<String^>(size);
or:
List<String^>^ list = gcnew List<String^>^();
You should use one of the types from System.Collections.Generic, for example System.Collections.Generic.List
There is a simple example at the bottom of that page.
StringCollection for instance,
or
List<String>
Related
I have created a simple DLL in C++, for the sole purpose of isolating the issue and testing on a small scale the importing of a function that returns a list of structs with members of different types.
dll_header.h
#ifdef MY_DLL_EXPORTS
#define MY_DLL_API __declspec(dllexport)
#else
#define MY_DLL_API __declspec(dllimport)
#endif
enum color_type
{
RGB = 1,
MONO = 2
};
struct my_struct
{
unsigned char *name;
char *value;
color_type type;
my_struct* next;
};
extern "C" struct my_struct MY_DLL_API * get_list(void);
dll_header.cpp
#include "dll_header.h"
MY_DLL_API my_struct * get_list(void)
{
my_struct my_list[2];
unsigned char name1[] = "name1";
unsigned char name2[] = "name2";
char val1[] = "val1";
char val2[] = "val2";
my_list[0].name = name1;
my_list[0].value = val1;
my_list[0].type = RGB;
my_list[0].next = &my_list[1];
my_list[0].name = name2;
my_list[0].value = val2;
my_list[0].type = MONO;
my_list[0].next = NULL;
return my_list;
}
Like I said, I have to use these data types (cannot change them to strings or anything else because I am testing something and I need them like this)
Now, in my VB.NET application I import and try to retrieve the list like this from the DLL
Form1.vb
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Form1
Public Enum color_type
RGB = 1
COLOR = 2
End Enum
Private Structure my_struct
Public name As Byte()
Public value As Char()
Public type As color_type
Public next As IntPtr
End Structure
Private Declare Function get_list Lib "my_lib.dll" () As IntPtr
Private my_list As List(Of my_struct)
Private Sub get_list()
Dim my_list_pointer As IntPtr = get_list()
my_list = New List(Of my_struct)
Dim my_item As my_struct
While my_list_pointer <> IntPtr.Zero
my_item = CType(Marshal.PtrToStructure(my_list_pointer, GetType(my_struct)), my_struct)
my_list.Add(my_item)
my_list_pointer = my_item.next
End While
End Sub
I have tried many other methods, specially changing data types but so far here I am, stuck with this exception when trying to run the code:
System.AccessViolationException: 'Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.'
Trying to find a way to make these two understand each other
Either use mixed mode C++ to do the translation between native and managed types or use types that are compatible with P/Invoke.
Looking how Win32 define structure (and function that use those) is a good start to help you understand how to define compatible structures as one of the main intent of P/Invoke is to be able to use Win32 API from managed code.
If you go for mixed mode, then you can do whatever required translation between both world as you can mix native C++ and C++/CLI in the same assembly. So essentially, you would write code that convert the native structure into a managed one and then VB.NET will be able to use that managed code (assuming that you use types available in VB.NET for example).
Well, if you go for the mixed mode route, you generally ends up with 3 DLLs/Assemblies/Executable as you would have the original C++ DLL (native code), the VB.NET code (managed) and the mixed mode C++ assembly in between.
Update
While it could be relatively easy to provide code if the list is read only, if this is not the case, it could be much harder depending how the code is expected to be used and what are the availaible function in the existing DLL.
The starting point would be to create a ref class in C++/CLI.
Some similar questions
https://bytes.com/topic/c-sharp/answers/674468-passing-linked-list-c-dll-c-pinvoke
Return list of points (x,y,z) from C to C# using PInvoke
PInvoke of self referential struct from C++
Problem with your code
Your exported function retuns a pointer to a local variable which is undefined behavior.
Additional observation
If your original list is an array, the why making it a list also? An array would be easier to marshal and use. And probably perform better too.
When defining you structure, you have be explicit on how strings are marshalled and the alignment that should be used. You shoull validate that everything is as expected.
This is the code that i do:
`void Tabella::on_pushButton_clicked()
{
int risultato;
risultato = ui->treeWidget->currentItem()->text(2);
ui->out_3->setText(QString::number(risultato));
}`
Are the any ways to assign the code into variable? Like that?
P.S I'm new in QT, i worked with c++ and java.
Try this:
ui->out_3->setText(ui->treeWidget->currentItem()->text());
You make take a look at this question
I want to add a string into C++ rest sdk json object. I tried
json::value obj;
obj[L"Login"] = json::value::string();
But the problem is this adds only strings as U("str") and not const std::string.
So I can add as
obj[L"Login"] = json::value::string(U("Login"));
but not do as follows:
json::value obj;
string Login= "login";
obj[L"Login"] = json::value::string(Login);
I am using C++ rest sdk 2.8.0.
Try the following type conversion:
json::value obj;
string Login= "login";
std::wstring_convert<std::codecvt_utf8<wchar_t> > converter;
std::wstring uLogin = converter.from_bytes(Login);
obj[L"Login"] = json::value::string(uLogin);
Better switch all your
std::string
to
std::wstring
objects.
cppRest only works with wide strings, so you will end up converting all over the place...
This is confusing. I understand pointers but what is with tracking references?
The instructions are not very clear on what to do even on the wiki, not to mention I was never taught this in adv C++. So, How do I get the items in a listbox into one of my classes?
Also is can i get a brief rundown of tracking references for future reference?
My form has a Listbox called listbox2 with some data in it.
My class called "ManifistOBJ" has a method called "setFilename(char*)"
Now in other programs i can easily add objects to the "AddFilename" method but how do i do it for a tracking reference?
Sofar iv tried:
DMManifest newmanifest = DMManifest();
for(int i =1;i< listBox2->Items->Count;i++)
{
ManifistOBJ newobj = ManifistOBJ();
System::String^ temp = listBox2->Items[i]->ToString();
String temp1 = temp;//?
char* temp2 = temp1.c_str();
newobj.setFilename(temp2);
newmanifest.push_back(newobj);
}
With that ^ next to string I cant DE-reference it. and I have no idea how to.
I could make the method take a string^ but that would mess up my other programs that use that library.
#include <msclr/marshal_cppstd.h>
System::String^ temp = listBox2->Items[i]->ToString();
std::string temp1 = msclr::interop::marshal_as< std::string >( temp );
C++/CLI Converting from System::String^ to std::string
i find below code that get keyboard layout but cant convert it to string :
TISInputSourceRef sourceRef = TISCopyCurrentKeyboardLayoutInputSource();
If you use CFShow(sourceRef); you can see keyboard layout but cant convert sourceRef.
How to get keyboardLayout in string ???
I use this objc code:
#import <Carbon/Carbon.h>
TISInputSourceRef source = TISCopyCurrentKeyboardInputSource();
NSString *s = (__bridge NSString *)(TISGetInputSourceProperty(source, kTISPropertyInputSourceID));
You can probably also cast it to CFStringRef instead of an objc string.