0

Hello i tried to export functions from c++ and tried to run it at c# but i got an error that System.AccessViolationException: An attempt to read or write protected memory. This is usually an indication that the other memory is corrupted., I did this thanks to microsoft example but i got this error and i cannot find anything about this. Am i wrong at any places ?

C++ header file

#ifndef KKKKK_V2_EXPORTS
#define KKKKK_V2_API __declspec(dllexport)
#else
#define KKKKK_V2_API __declspec(dllimport)
#endif

extern "C" KKKKK_V2_API can* create_can(string ip, int port);

extern "C" KKKKK_V2_API int connectCan(can* _c);


extern "C" KKKKK_V2_API string browseCan(can* _c,int x);

extern "C" KKKKK_V2_API void dataset_browseCan(can* _c);

extern "C" KKKKK_V2_API void dataset_signals_readingCan(can* _c);

extern "C" KKKKK_V2_API void GI_Can(can* _c);

extern "C" KKKKK_V2_API void ConcludeCan(can* _c);

Cpp file

can* create_can(string ip, int port) {
    const char* my_ip=ip.c_str();
    can* _c = new can();
    _c->connection = new connect_tcp((char*)my_ip, port);
    _c->s = _c->connection->ConnectWithTcp();
    _c->list = new LinkedList * [1000];
    return _c;
}
int connectCan(can* _c) {
    cotp_connection(_c->cotp, _c->connection, _c->response, _c->list, _c->s);
    return 1;
}
string browseCan(can* _c,int x) {
    int i = 0;
    initiate_request(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s);
    confirmed_request(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s);
    continue_confirmed_request_with_more_follows(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s);
    all_object_browse(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s);
    auto it = _c->response.object_list.begin();
    while (i < x) {
        it++;
        i++;
    }
    return *it; 
}
void dataset_browseCan(can* _c) {
    dataset_browse(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s);
    dataset_signals_browse(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s); 
    _c->signals = new Signals[_c->response.real_signals_and_values.size()];
}
void dataset_signals_readingCan(can* _c) {
    dataset_signals_reading(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s, _c->signals);
}
void GI_Can(can* _c) {
    write_data_pins(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s, _c->signals);
    general_information(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s, _c->signals);
}
void ConcludeCan(can* _c) {
    conclude(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s, _c->signals);
    release(_c->cotp, _c->mms_obj, _c->connection, _c->response, _c->list, _c->size_encoder, _c->s, _c->signals);
}

C# file

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace cppDllTest
{
    class Program
    {

        [DllImport(@"C:\Users\serhan.erkovan\source\repos\kkkkk_v2\Debug\kkkkk_v2.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern IntPtr create_can(string my_ip_address, int my_port);
        IntPtr _c;
        _c = create_can("10.6.35.225", 102);   //ERROR IS HERE
    }
}

I put my cpp file but it is not necessary, i know.Maybe i am wrong at cpp file because of this ı put that.

At Dependency Walker my all functions that export seems grey at 'E' section.That's meaning is " C export function that resides in the selected module."

Serhan Erkovan
  • 481
  • 4
  • 18
  • Which platform did you pick in "Platform for Build"? Maybe this top answer could help : https://stackoverflow.com/a/18252141/3852949 – Storm Dec 19 '19 at 13:18
  • @Storm Visual Studio 2019 (v142) i build for x64 and x86 but got this error every time – Serhan Erkovan Dec 19 '19 at 13:21
  • Have you tried compiling your c++ code and checked if the compiled binary works as expected before interfacing it with P/Invoke? As a sidenote I'd like to point that `_c->connection = new connect_tcp((char*)my_ip, port);` will result in a dangling pointer as the pointer returned by `ip.c_str()` won't be valid anymore when you leave the scope since it's based on a temporary variable. – Storm Dec 19 '19 at 13:36
  • It is working on c++ ,i tried it wit no errors. – Serhan Erkovan Dec 19 '19 at 13:46
  • 1
    Try changing `can* create_can(string ip, int port)` prototype to `can* create_can(const char * ip, int port)` and change the c++ code accordingly. The type `string` in C# doesn't equate to `std::string` in C++. – Storm Dec 19 '19 at 13:53
  • I add a exportable function named 'sum' that get no parameter instead of your opinion and it worked but i dont understood why pointer function is not worked – Serhan Erkovan Dec 19 '19 at 14:05
  • now i get an error that "external component has generated an exception" – Serhan Erkovan Dec 19 '19 at 14:19

1 Answers1

1

The issue here is that, as explained here https://stackoverflow.com/a/20752021/3852949 :

You cannot pass a C++ std::string across an interop boundary. You cannot create one of those in your C# code

You could either change the C++ function signature so that it accepts a const char * (i.e can* create_can(const char * ip, int port)) or create an adapter function calling your original function :

can* create_can_adapter(const char * ip, int port)
{
    std::string s(ip);

    return (create_can(s, port));
}
Storm
  • 717
  • 6
  • 11