On Wednesday, 14 October 2015 at 12:35:30 UTC, Rainer Schuetze wrote:

I just noticed that the magic symbol translation _snprintf -> __snprintf isn't included without linking the internal function init_msvc (which is normally done by d_run_main which is called by the generated C main).


The current workaround here is to add

extern "C" void __cdecl init_msvc();

to the C source and call it before rt_init. I think we should move it into rt_init inside druntime.

This indeed helps, thanks!

There is new problem: creating a class instance on D side, then passing it to C++ and then back to D causes casting errors. My Example (based on Adam Ruppe's example):

C++ file:

#include <iostream>
#include <stdio.h>

extern "C" int rt_init();
extern "C" void rt_term();

extern "C++" int sumInD(int a, int b);
extern "C++" void printHelloInD();


class Operation {
public:

  virtual ~Operation() {}

  virtual int execute(int a, int b) = 0;
};

class Add : public Operation
{
  int execute(int a, int b) override
  {
    return a + b;
  }
};

extern "C++" void useOperation(Operation* t);
extern "C++" Operation* getSubtract();
extern "C++" void freeSubtract(Operation* cat);

struct DRuntime
{
  DRuntime()
  {
    if (!rt_init())\
    {
      throw std::runtime_error("D Initialization failed");
    }
  }

  ~DRuntime()
  {
    rt_term();
  }
};

void main()
{
  DRuntime druntime;
  Add add;

  useOperation(&add);

  Operation* sub = getSubtract();
  auto value = sub->execute(5, 3);
  freeSubtract(sub);

}

D library:

module lib;
import std.stdio;
import core.stdc.stdlib;

int main()
{
  return 0;
}

extern(C++)
interface Operation {
  void _destructorDoNotUse();
  int execute(int a, int b);
}
class Subtract : Operation {

  extern(C++)
    void _destructorDoNotUse() {}
  extern(C++)
    int execute(int a, int b) {return a - b;}
}

extern(C++)
Operation getSubtract() {
  import std.conv;
  enum size = __traits(classInstanceSize, Subtract);
  auto memory = malloc(size)[0 .. size];
  return emplace!Subtract(memory);
}

extern (C++) int sumInD(int a, int b)
{
  return a + b;
}

extern (C++) void printHelloInD()
{
writeln("Hello From D!"); << ===== throws exception (bug reported)
}

extern(C++)
void freeSubtract(Operation animal) {
  auto cat = cast(Subtract) animal; <<====== cast yields null
  if(cat !is null) {
    destroy(cat);
    free(cast(void*) cat);
  }
}

extern(C++)
void useOperation(Operation t) {
  auto res = t.execute(1, 2);
}

Everything works fine except the marked line. Subtract instance seems to be created correctly on D side as it returns valid result in the execute() call on C++ side but then when trying to free the instance on D side again, downcast from Operation to Subtract fails resulting in null.


Reply via email to